add example
This commit is contained in:
8
.gitignore
vendored
8
.gitignore
vendored
@@ -6,3 +6,11 @@ yarn-error.log
|
||||
.vercel_build_output
|
||||
build
|
||||
dist
|
||||
|
||||
/yarn-error.log
|
||||
|
||||
# umi
|
||||
.umi
|
||||
.umi-production
|
||||
.umi-test
|
||||
.env.local
|
||||
|
@@ -2,3 +2,11 @@
|
||||
static/**
|
||||
build/**
|
||||
node_modules/**
|
||||
**/*.md
|
||||
**/*.svg
|
||||
**/*.ejs
|
||||
**/*.html
|
||||
package.json
|
||||
.umi
|
||||
.umi-production
|
||||
.umi-test
|
||||
|
@@ -5,6 +5,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"start": "lerna exec npm run start --scope=dooringx-lib",
|
||||
"start:example":"lerna exec npm run start --scope=dooringx-example",
|
||||
"start:doc":"lerna exec npm run start --scope=dooringx-doc",
|
||||
"build": "lerna exec npm run build --scope=dooringx-lib",
|
||||
"deploy": "lerna exec npm run deploy --scope=dooringx-doc",
|
||||
"pub": "node ./script/publish.js"
|
||||
|
16
packages/dooringx-example/.editorconfig
Normal file
16
packages/dooringx-example/.editorconfig
Normal file
@@ -0,0 +1,16 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
35
packages/dooringx-example/.umirc.ts
Normal file
35
packages/dooringx-example/.umirc.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 11:11:52
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 20:18:39
|
||||
* @FilePath: \visual-editor\.umirc.ts
|
||||
*/
|
||||
import { defineConfig } from 'umi';
|
||||
|
||||
export default defineConfig({
|
||||
nodeModulesTransform: {
|
||||
type: 'none',
|
||||
},
|
||||
dynamicImport: {
|
||||
loading: '@/components/Loading',
|
||||
},
|
||||
locale: {
|
||||
default: 'zh-CN',
|
||||
antd: true,
|
||||
baseNavigator: true,
|
||||
},
|
||||
routes: [
|
||||
{
|
||||
exact: false,
|
||||
path: '/',
|
||||
component: '@/layouts/index',
|
||||
routes: [
|
||||
{ path: '/', component: '@/pages/index' },
|
||||
{ path: '/preview', component: '@/pages/preview' },
|
||||
{ path: '/iframe', component: '@/pages/iframe' },
|
||||
],
|
||||
},
|
||||
],
|
||||
fastRefresh: {},
|
||||
});
|
15
packages/dooringx-example/README.md
Normal file
15
packages/dooringx-example/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# umi project
|
||||
|
||||
## Getting Started
|
||||
|
||||
Install dependencies,
|
||||
|
||||
```bash
|
||||
$ yarn
|
||||
```
|
||||
|
||||
Start the dev server,
|
||||
|
||||
```bash
|
||||
$ yarn start
|
||||
```
|
0
packages/dooringx-example/mock/.gitkeep
Normal file
0
packages/dooringx-example/mock/.gitkeep
Normal file
43
packages/dooringx-example/package.json
Normal file
43
packages/dooringx-example/package.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name":"dooringx-example",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "umi dev",
|
||||
"build": "umi build",
|
||||
"postinstall": "umi generate tmp",
|
||||
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
|
||||
"test": "umi-test",
|
||||
"test:coverage": "umi-test --coverage"
|
||||
},
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,less,md,json}": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.ts?(x)": [
|
||||
"prettier --parser=typescript --write"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^4.6.2",
|
||||
"antd": "^4.15.2",
|
||||
"@ant-design/pro-layout": "^6.5.0",
|
||||
"@umijs/preset-react": "1.x",
|
||||
"umi": "^3.5.4",
|
||||
"animate.css": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@umijs/test": "^3.5.4",
|
||||
"lint-staged": "^10.0.7",
|
||||
"prettier": "^2.2.0",
|
||||
"react": "17.x",
|
||||
"react-dom": "17.x",
|
||||
"typescript": "^4.1.2",
|
||||
"yorkie": "^2.0.0"
|
||||
}
|
||||
}
|
11
packages/dooringx-example/src/components/Loading.tsx
Normal file
11
packages/dooringx-example/src/components/Loading.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:59:34
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 15:00:05
|
||||
* @FilePath: \visual-editor\src\components\Loading.tsx
|
||||
*/
|
||||
function Loading() {
|
||||
return <div>loading</div>;
|
||||
}
|
||||
export default Loading;
|
8
packages/dooringx-example/src/constant/index.ts
Normal file
8
packages/dooringx-example/src/constant/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 20:11:11
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 20:11:29
|
||||
* @FilePath: \visual-editor\src\constant\index.ts
|
||||
*/
|
||||
export const PREVIEWSTATE = 'PREVIEWSTATE';
|
3
packages/dooringx-example/src/global.less
Normal file
3
packages/dooringx-example/src/global.less
Normal file
@@ -0,0 +1,3 @@
|
||||
.ant-menu-title-content {
|
||||
margin: 0 !important;
|
||||
}
|
54
packages/dooringx-example/src/layouts/index.tsx
Normal file
54
packages/dooringx-example/src/layouts/index.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:51:17
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 19:07:10
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\layouts\index.tsx
|
||||
*/
|
||||
import { Button } from 'antd';
|
||||
import { UserConfig } from 'dooringx-lib/dist';
|
||||
import 'dooringx-lib/dist/dooringx-lib.esm.css';
|
||||
import { createContext } from 'react';
|
||||
import { IRouteComponentProps } from 'umi';
|
||||
import plugin from '../plugin';
|
||||
import 'antd/dist/antd.css';
|
||||
import 'dooringx-lib/dist/dooringx-lib.esm';
|
||||
import '../global.less';
|
||||
import 'animate.css';
|
||||
|
||||
export const config = new UserConfig(plugin);
|
||||
export const configContext = createContext<UserConfig>(config);
|
||||
// 自定义右键
|
||||
const contextMenuState = config.getContextMenuState();
|
||||
const unmountContextMenu = contextMenuState.unmountContextMenu;
|
||||
const commander = config.getCommanderRegister();
|
||||
const ContextMenu = () => {
|
||||
const handleclick = () => {
|
||||
unmountContextMenu();
|
||||
};
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
left: contextMenuState.left,
|
||||
top: contextMenuState.top,
|
||||
position: 'fixed',
|
||||
background: 'rgb(24, 23, 23)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ width: '100%' }}
|
||||
onClick={() => {
|
||||
commander.exec('redo');
|
||||
handleclick();
|
||||
}}
|
||||
>
|
||||
<Button>自定义</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
contextMenuState.contextMenu = <ContextMenu></ContextMenu>;
|
||||
|
||||
export default function Layout({ children }: IRouteComponentProps) {
|
||||
return <configContext.Provider value={config}>{children}</configContext.Provider>;
|
||||
}
|
22
packages/dooringx-example/src/pages/iframe/index.tsx
Normal file
22
packages/dooringx-example/src/pages/iframe/index.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 20:16:00
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 22:18:55
|
||||
* @FilePath: \visual-editor\src\pages\iframe\index.tsx
|
||||
*/
|
||||
|
||||
function IframePage() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<iframe style={{ width: '375px', height: '667px' }} src="/preview"></iframe>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default IframePage;
|
0
packages/dooringx-example/src/pages/index.less
Normal file
0
packages/dooringx-example/src/pages/index.less
Normal file
82
packages/dooringx-example/src/pages/index.tsx
Normal file
82
packages/dooringx-example/src/pages/index.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-05-15 12:49:28
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 19:08:25
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\pages\index.tsx
|
||||
*/
|
||||
import {
|
||||
RightConfig,
|
||||
Container,
|
||||
useStoreState,
|
||||
innerContainerDragUp,
|
||||
LeftConfig,
|
||||
ContainerWrapper,
|
||||
Control,
|
||||
} from 'dooringx-lib';
|
||||
import { useContext } from 'react';
|
||||
import { configContext } from '@/layouts';
|
||||
import { useCallback } from 'react';
|
||||
import { PREVIEWSTATE } from '@/constant';
|
||||
|
||||
export const HeaderHeight = '40px';
|
||||
|
||||
export default function IndexPage() {
|
||||
const config = useContext(configContext);
|
||||
|
||||
const everyFn = () => {};
|
||||
|
||||
const subscribeFn = useCallback(() => {
|
||||
localStorage.setItem(PREVIEWSTATE, JSON.stringify(config.getStore().getData()));
|
||||
}, [config]);
|
||||
|
||||
const [state] = useStoreState(config, subscribeFn, everyFn);
|
||||
|
||||
return (
|
||||
<div {...innerContainerDragUp()}>
|
||||
<div style={{ height: HeaderHeight }}>
|
||||
head
|
||||
<button
|
||||
onClick={() => {
|
||||
window.open('/iframe');
|
||||
}}
|
||||
>
|
||||
go preview
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
window.open('/preview');
|
||||
}}
|
||||
>
|
||||
go preview
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: `calc(100vh - ${HeaderHeight})`,
|
||||
width: '100vw',
|
||||
}}
|
||||
>
|
||||
<div style={{ height: '100%' }}>
|
||||
<LeftConfig config={config}></LeftConfig>
|
||||
</div>
|
||||
|
||||
<ContainerWrapper>
|
||||
<>
|
||||
<Control
|
||||
config={config}
|
||||
style={{ position: 'fixed', bottom: '60px', right: '450px' }}
|
||||
></Control>
|
||||
<Container state={state} config={config} context="edit"></Container>
|
||||
</>
|
||||
</ContainerWrapper>
|
||||
<div className="rightrender" style={{ height: '100%' }}>
|
||||
<RightConfig state={state} config={config}></RightConfig>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
38
packages/dooringx-example/src/pages/preview/index.tsx
Normal file
38
packages/dooringx-example/src/pages/preview/index.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 20:05:48
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 18:01:15
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\pages\preview\index.tsx
|
||||
*/
|
||||
|
||||
import { PREVIEWSTATE } from '@/constant';
|
||||
import { Preview, UserConfig } from 'dooringx-lib';
|
||||
import plugin from '../../plugin';
|
||||
|
||||
const config = new UserConfig(plugin);
|
||||
|
||||
function PreviewPage() {
|
||||
const data = localStorage.getItem(PREVIEWSTATE);
|
||||
if (data) {
|
||||
try {
|
||||
const json = JSON.parse(data);
|
||||
config.resetData([json]);
|
||||
} catch {
|
||||
console.log('err');
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Preview config={config}></Preview>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PreviewPage;
|
20
packages/dooringx-example/src/plugin/commanderModules.ts
Normal file
20
packages/dooringx-example/src/plugin/commanderModules.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:27:01
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 14:27:38
|
||||
* @FilePath: \visual-editor\src\plugin\commanderModules.ts
|
||||
*/
|
||||
|
||||
import { CommanderItem } from 'dooringx-lib/dist/core/command/commanderType';
|
||||
|
||||
const modulesFiles = (require as any).context('./commands', true, /\.(js|ts)$/);
|
||||
const commandModules: CommanderItem[] = modulesFiles
|
||||
.keys()
|
||||
.reduce((modules: any, modulePath: any) => {
|
||||
const value = modulesFiles(modulePath);
|
||||
modules.push(value.default);
|
||||
return modules;
|
||||
}, []);
|
||||
|
||||
export default commandModules;
|
18
packages/dooringx-example/src/plugin/commands/redo.ts
Normal file
18
packages/dooringx-example/src/plugin/commands/redo.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:28:20
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 14:28:28
|
||||
* @FilePath: \visual-editor\src\plugin\commands\redo.ts
|
||||
*/
|
||||
import { CommanderItemFactory } from 'dooringx-lib';
|
||||
const undo = new CommanderItemFactory(
|
||||
'redo',
|
||||
'Control+Shift+z',
|
||||
(store) => {
|
||||
store.redo();
|
||||
},
|
||||
'重做'
|
||||
);
|
||||
|
||||
export default undo;
|
19
packages/dooringx-example/src/plugin/commands/undo.ts
Normal file
19
packages/dooringx-example/src/plugin/commands/undo.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:28:00
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 14:28:08
|
||||
* @FilePath: \visual-editor\src\plugin\commands\undo.ts
|
||||
*/
|
||||
import { CommanderItemFactory } from 'dooringx-lib';
|
||||
|
||||
const undo = new CommanderItemFactory(
|
||||
'undo',
|
||||
'Control+z',
|
||||
(store) => {
|
||||
store.undo();
|
||||
},
|
||||
'撤销'
|
||||
);
|
||||
|
||||
export default undo;
|
21
packages/dooringx-example/src/plugin/formComponentModules.ts
Normal file
21
packages/dooringx-example/src/plugin/formComponentModules.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:29:38
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-09 13:51:32
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\registFormComponents.ts
|
||||
*
|
||||
*/
|
||||
|
||||
import { ComponentClass } from 'react';
|
||||
import { FunctionComponent } from 'react';
|
||||
|
||||
const modulesFiles = (require as any).context('./formComponents', true, /\.(js|tsx)$/);
|
||||
export const Formmodules: Record<string, FunctionComponent<any> | ComponentClass<any, any>> =
|
||||
modulesFiles.keys().reduce((modules: any, modulePath: any) => {
|
||||
const tmp = modulePath.split('.');
|
||||
const name = tmp[tmp.length - 2].slice(1);
|
||||
const value = modulesFiles(modulePath);
|
||||
modules[name] = value.default;
|
||||
return modules;
|
||||
}, []);
|
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:46:01
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 18:33:35
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\formComponents\actionButton.tsx
|
||||
*/
|
||||
|
||||
import { Button, Col, Input, message, Modal, Row, Select } from 'antd';
|
||||
import { memo, useMemo, useState } from 'react';
|
||||
import React from 'react';
|
||||
import { UserConfig, createUid, deepCopy } from 'dooringx-lib';
|
||||
import { unstable_batchedUpdates } from 'react-dom';
|
||||
import { FormMap } from '../formTypes';
|
||||
import { CreateOptionsRes } from 'dooringx-lib/dist/core/components/formTypes';
|
||||
import { IBlockType, IStoreData } from 'dooringx-lib/dist/core/store/storetype';
|
||||
import { FunctionConfigType } from 'dooringx-lib/dist/core/functionCenter/config';
|
||||
import { EventCenterUserSelect } from 'dooringx-lib/dist/core/eventCenter';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
interface ActionButtonProps {
|
||||
data: CreateOptionsRes<FormMap, 'actionButton'>;
|
||||
current: IBlockType;
|
||||
config: UserConfig;
|
||||
}
|
||||
|
||||
function ActionButton(props: ActionButtonProps) {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [cur, setCur] = useState('');
|
||||
|
||||
const eventMap = props.config.getEventCenter().getEventMap();
|
||||
const currentOption = useMemo(() => {
|
||||
return Object.keys(eventMap).filter((v) => v.indexOf(props.current.id) >= 0);
|
||||
}, [eventMap, props.current.id]);
|
||||
|
||||
const [search, setSearch] = useState<EventCenterUserSelect[]>([]);
|
||||
const functionCenter = props.config.getEventCenter().getFunctionCenter();
|
||||
const functionConfig = functionCenter.getConfigMap();
|
||||
const functionMap = functionCenter.getFunctionMap();
|
||||
const isEdit = props.config.getStoreChanger().isEdit();
|
||||
const dataMap = props.config.getDataCenter().getDataMap();
|
||||
let modalMap: Record<string, IStoreData>;
|
||||
if (isEdit) {
|
||||
modalMap = props.config.getStoreChanger().getOrigin()?.now.modalMap || {};
|
||||
} else {
|
||||
modalMap = props.config.getStore().getData().modalMap;
|
||||
}
|
||||
|
||||
const handleInputDataSource = (
|
||||
w: {
|
||||
uid: string;
|
||||
value: string;
|
||||
detail: Record<string, any>;
|
||||
},
|
||||
c: any,
|
||||
name = 'dataSource'
|
||||
) => {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
textAlign: 'right',
|
||||
margin: '10px 0',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
if (v.uid === w.uid) {
|
||||
let sign = true;
|
||||
if (!v.detail[name][c.name]) {
|
||||
v.detail[name][c.name] = [];
|
||||
}
|
||||
if (!c.options.multi) {
|
||||
if (v.detail[name][c.name].length >= 1) {
|
||||
sign = false;
|
||||
message.error('该函数最多只能添加1个');
|
||||
}
|
||||
}
|
||||
if (sign) {
|
||||
v.detail[name][c.name].push('');
|
||||
}
|
||||
}
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
添加
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
{w.detail[name] &&
|
||||
w.detail[name][c.name] &&
|
||||
w.detail[name][c.name].map((vvv: string, x: number) => {
|
||||
return (
|
||||
<Row key={x}>
|
||||
<Col span={19}>
|
||||
<Select
|
||||
style={{ width: '100%' }}
|
||||
value={vvv}
|
||||
onChange={(e) => {
|
||||
const value = e;
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
v.uid === w.uid ? (v.detail[name][c.name][x] = value || '') : '';
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
{Object.keys(dataMap).map((n) => {
|
||||
return (
|
||||
<Option key={n} value={n}>
|
||||
{n}
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={5} style={{ textAlign: 'right' }}>
|
||||
<Button
|
||||
danger
|
||||
onClick={() => {
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
v.uid === w.uid ? v.detail[name][c.name].splice(x, 1) : '';
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const handleInput = (
|
||||
w: {
|
||||
uid: string;
|
||||
value: string;
|
||||
detail: Record<string, any>;
|
||||
},
|
||||
c: any,
|
||||
name = 'ctx'
|
||||
) => {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
textAlign: 'right',
|
||||
margin: '10px 0',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
if (v.uid === w.uid) {
|
||||
if (!v.detail[name][c.name]) {
|
||||
v.detail[name][c.name] = [];
|
||||
}
|
||||
let sign = true;
|
||||
if (!c.options.multi) {
|
||||
if (v.detail[name][c.name].length >= 1) {
|
||||
sign = false;
|
||||
message.error('该函数最多只能添加1个');
|
||||
}
|
||||
}
|
||||
if (sign) {
|
||||
v.detail[name][c.name].push('');
|
||||
}
|
||||
}
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
添加输入框
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
{w.detail[name] &&
|
||||
w.detail[name][c.name] &&
|
||||
w.detail[name][c.name].map((vvv: string, x: number) => {
|
||||
return (
|
||||
<Row key={x}>
|
||||
<Col span={19}>
|
||||
<Input
|
||||
value={vvv}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
v.uid === w.uid ? (v.detail[name][c.name][x] = value || '') : '';
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
></Input>
|
||||
</Col>
|
||||
<Col span={5} style={{ textAlign: 'right' }}>
|
||||
<Button
|
||||
danger
|
||||
onClick={() => {
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
v.uid === w.uid ? v.detail[name][c.name].splice(x, 1) : '';
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: '10px 20px' }}>
|
||||
<Row
|
||||
style={{
|
||||
padding: 20,
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Col span={8}>标识ID</Col>
|
||||
<Col span={16}>{props.current.id}</Col>
|
||||
</Row>
|
||||
{currentOption.map((j, i) => {
|
||||
return (
|
||||
<Row
|
||||
key={i}
|
||||
style={{
|
||||
padding: 20,
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<div>{eventMap[j].displayName}</div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
unstable_batchedUpdates(() => {
|
||||
setVisible(true);
|
||||
setCur((pre) => {
|
||||
if (pre !== j) {
|
||||
//查找该cur的选项
|
||||
const store = props.config.getStore().getData();
|
||||
let init: EventCenterUserSelect[] = [];
|
||||
store.block.forEach((v) => {
|
||||
if (v.id === props.current.id) {
|
||||
init = v.eventMap[j]?.userSelect || [];
|
||||
}
|
||||
});
|
||||
setSearch(init);
|
||||
}
|
||||
return j;
|
||||
});
|
||||
});
|
||||
}}
|
||||
>
|
||||
配置
|
||||
</Button>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
<Modal
|
||||
width={800}
|
||||
title={'事件编辑' + `-${(eventMap[cur] && eventMap[cur].displayName) || ''}`}
|
||||
forceRender
|
||||
onOk={() => {
|
||||
// 更新store中的eventMap
|
||||
const store = props.config.getStore();
|
||||
const cloneData: IStoreData = deepCopy(store.getData());
|
||||
const arr = search.map((v) => {
|
||||
// name: string; // 函数名
|
||||
// args: Record<string, any>; // 输入参数都会变成对象传来,
|
||||
// data: Record<string, FunctionDataType>; // 用户选的种类 键是每个配置项名
|
||||
const name = v.value; //函数名
|
||||
const options: FunctionConfigType = functionConfig[name];
|
||||
const dataMap = v.detail['data'];
|
||||
const combine = options.map((jkk) => {
|
||||
const select: string = dataMap[jkk.name]; // datasource / input / modal
|
||||
let val = {};
|
||||
if (select) {
|
||||
const value = v.detail[select]; //{name:array<>}
|
||||
const receive = jkk.options.receive;
|
||||
val = { [receive]: value[jkk.name] }; //这里不能换算,否则修改data后值不会更新
|
||||
}
|
||||
|
||||
const choose = { [jkk.name]: select };
|
||||
return {
|
||||
...v,
|
||||
choose,
|
||||
val,
|
||||
};
|
||||
});
|
||||
const combineVal = combine.reduce((prev, next) => {
|
||||
return Object.assign(prev, next.val);
|
||||
}, {});
|
||||
const combineChoose = combine.reduce((prev, next) => {
|
||||
return Object.assign(prev, next.choose);
|
||||
}, {});
|
||||
|
||||
return {
|
||||
name: name,
|
||||
data: combineChoose,
|
||||
args: combineVal,
|
||||
};
|
||||
});
|
||||
let displayName = '';
|
||||
cloneData.block.forEach((v) => {
|
||||
if (v.id === props.current.id) {
|
||||
v.eventMap[cur].userSelect = search;
|
||||
v.eventMap[cur].arr = arr;
|
||||
displayName = v.eventMap[cur].displayName;
|
||||
}
|
||||
});
|
||||
const eventCenter = props.config.getEventCenter();
|
||||
eventCenter.manualUpdateMap(cur, displayName, arr);
|
||||
store.setData(cloneData);
|
||||
setVisible(false);
|
||||
}}
|
||||
onCancel={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
visible={visible}
|
||||
>
|
||||
<div>
|
||||
<Row align="middle">
|
||||
<Col span={6}>触发事件ID:</Col>
|
||||
<Col span={18}>{cur}</Col>
|
||||
</Row>
|
||||
<Row justify="space-between" style={{ justifyContent: 'flex-end', margin: '20px 0' }}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setSearch((pre) => {
|
||||
pre.push({
|
||||
uid: createUid(),
|
||||
value: '',
|
||||
detail: {
|
||||
input: {},
|
||||
ctx: {},
|
||||
dataSource: {},
|
||||
data: {},
|
||||
modal: {},
|
||||
},
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
添加事件
|
||||
</Button>
|
||||
</Row>
|
||||
<div>
|
||||
{search.map((w, i) => {
|
||||
const current = search.find((v) => v.uid === w.uid);
|
||||
const options: FunctionConfigType | undefined = functionConfig[current?.value || ''];
|
||||
return (
|
||||
<div key={w.uid}>
|
||||
<Row align="middle">
|
||||
<Col span={6}>选择函数:</Col>
|
||||
<Col span={14}>
|
||||
<Select
|
||||
value={current?.value || ''}
|
||||
style={{ width: '100%' }}
|
||||
optionFilterProp="children"
|
||||
filterOption={(input, option) =>
|
||||
option!.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}
|
||||
onChange={(e) => {
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
// 切换选择要把下一级制空
|
||||
if (v.uid === w.uid) {
|
||||
v.value = e as string;
|
||||
v.detail['data'] = {};
|
||||
}
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
{Object.keys(functionMap).map((v) => {
|
||||
return (
|
||||
<Option key={v} value={v}>
|
||||
{v}
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={4} style={{ textAlign: 'right' }}>
|
||||
<Button
|
||||
danger
|
||||
onClick={() => {
|
||||
setSearch((pre) => {
|
||||
pre.splice(i, 1);
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<div
|
||||
//[{data: ""
|
||||
/// name: "改变文本数据源"
|
||||
//options: {receive: "_changeval"}}]
|
||||
>
|
||||
{options &&
|
||||
options.map((c) => {
|
||||
return (
|
||||
<Row key={c.name} style={{ margin: '10px 0' }}>
|
||||
<Col span={6}>{c.name}:</Col>
|
||||
<Col span={18}>
|
||||
{
|
||||
<Select
|
||||
value={current?.detail?.data?.[c.name] || ''}
|
||||
style={{ width: '100%' }}
|
||||
onChange={(e) => {
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
v.uid === w.uid
|
||||
? (v.detail['data'][c.name] = (e as string) || '')
|
||||
: '';
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
>
|
||||
{c.data.includes('dataSource') && (
|
||||
<Option value="dataSource">数据源</Option>
|
||||
)}
|
||||
{c.data.includes('ctx') && <Option value="ctx">上下文</Option>}
|
||||
{c.data.includes('input') && (
|
||||
<Option value="input">输入框</Option>
|
||||
)}
|
||||
{c.data.includes('modal') && (
|
||||
<Option value="modal">弹窗选择</Option>
|
||||
)}
|
||||
</Select>
|
||||
}
|
||||
|
||||
{w.detail['data'] && w.detail['data'][c.name] === 'dataSource' && (
|
||||
<div>{handleInputDataSource(w, c)}</div>
|
||||
)}
|
||||
{w.detail['data'] && w.detail['data'][c.name] === 'ctx' && (
|
||||
<div>{handleInput(w, c, 'ctx')}</div>
|
||||
)}
|
||||
{w.detail['data'] && w.detail['data'][c.name] === 'input' && (
|
||||
<div>{handleInput(w, c, 'input')}</div>
|
||||
)}
|
||||
{w.detail['data'] && w.detail['data'][c.name] === 'modal' && (
|
||||
<div>
|
||||
<Select
|
||||
value={w.detail['modal'][c.name] || ''}
|
||||
onChange={(e) => {
|
||||
setSearch((pre) => {
|
||||
pre.forEach((v) => {
|
||||
v.uid === w.uid
|
||||
? (v.detail['modal'][c.name] = (e as string) || '')
|
||||
: '';
|
||||
});
|
||||
return [...pre];
|
||||
});
|
||||
}}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{Object.keys(modalMap).map((v) => {
|
||||
return (
|
||||
<Option key={v} value={v}>
|
||||
{v}
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(ActionButton);
|
@@ -0,0 +1,309 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { UserConfig, deepCopy } from 'dooringx-lib';
|
||||
import { Col, Row, Select, InputNumber } from 'antd';
|
||||
import { FormMap, FormBaseType } from '../formTypes';
|
||||
import { CreateOptionsRes } from 'dooringx-lib/dist/core/components/formTypes';
|
||||
import { IBlockType } from 'dooringx-lib/dist/core/store/storetype';
|
||||
|
||||
export interface FormAnimateControlType extends FormBaseType {}
|
||||
|
||||
interface AnimateControlProps {
|
||||
data: CreateOptionsRes<FormMap, 'animateControl'>;
|
||||
current: IBlockType;
|
||||
config: UserConfig;
|
||||
}
|
||||
|
||||
//类型待修改
|
||||
const animateCategory: Record<string, string> = {
|
||||
'': '无',
|
||||
animate__bounce: 'bounce',
|
||||
animate__flash: 'flash',
|
||||
animate__pulse: 'pulse',
|
||||
animate__rubberBand: 'rubberBand',
|
||||
animate__shakeX: 'shakeX',
|
||||
animate__shakeY: 'shakeY',
|
||||
animate__headShake: 'headShake',
|
||||
animate__swing: 'swing',
|
||||
animate__tada: 'tada',
|
||||
animate__wobble: 'wobble',
|
||||
animate__jello: 'jello',
|
||||
animate__heartBeat: 'heartBeat',
|
||||
animate__backInDown: 'backInDown',
|
||||
animate__backInLeft: 'backInLeft',
|
||||
animate__backInRight: 'backInRight',
|
||||
animate__backInUp: 'backInUp',
|
||||
animate__backOutDown: 'backOutDown',
|
||||
animate__backOutLeft: 'backOutLeft',
|
||||
animate__backOutRight: 'backOutRight',
|
||||
animate__backOutUp: 'backOutUp',
|
||||
animate__bounceIn: 'bounceIn',
|
||||
animate__bounceInDown: 'bounceInDown',
|
||||
animate__bounceInLeft: 'bounceInLeft',
|
||||
animate__bounceInRight: 'bounceInRight',
|
||||
animate__bounceInUp: 'bounceInUp',
|
||||
animate__bounceOut: 'bounceOut',
|
||||
animate__bounceOutDown: 'bounceOutDown',
|
||||
animate__bounceOutLeft: 'bounceOutLeft',
|
||||
animate__bounceOutRight: 'bounceOutRight',
|
||||
animate__bounceOutUp: 'bounceOutUp',
|
||||
animate__fadeIn: 'fadeIn',
|
||||
animate__fadeInDown: 'fadeInDown',
|
||||
animate__fadeInDownBig: 'fadeInDownBig',
|
||||
animate__fadeInLeft: 'fadeInLeft',
|
||||
animate__fadeInLeftBig: 'fadeInLeftBig',
|
||||
animate__fadeInRight: 'fadeInRight',
|
||||
animate__fadeInRightBig: 'fadeInRightBig',
|
||||
animate__fadeInUp: 'fadeInUp',
|
||||
animate__fadeInUpBig: 'fadeInUpBig',
|
||||
animate__fadeInTopLeft: 'fadeInTopLeft',
|
||||
animate__fadeInTopRight: 'fadeInTopRight',
|
||||
animate__fadeInBottomLeft: 'fadeInBottomLeft',
|
||||
animate__fadeInBottomRight: 'fadeInBottomRight',
|
||||
animate__fadeOut: 'fadeOut',
|
||||
animate__fadeOutDown: 'fadeOutDown',
|
||||
animate__fadeOutDownBig: 'fadeOutDownBig',
|
||||
animate__fadeOutLeft: 'fadeOutLeft',
|
||||
animate__fadeOutLeftBig: 'fadeOutLeftBig',
|
||||
animate__fadeOutRight: 'fadeOutRight',
|
||||
animate__fadeOutRightBig: 'fadeOutRightBig',
|
||||
animate__fadeOutUp: 'fadeOutUp',
|
||||
animate__fadeOutUpBig: 'fadeOutUpBig',
|
||||
animate__fadeOutTopLeft: 'fadeOutTopLeft',
|
||||
animate__fadeOutTopRight: 'fadeOutTopRight',
|
||||
animate__fadeOutBottomRight: 'fadeOutBottomRight',
|
||||
animate__fadeOutBottomLeft: 'fadeOutBottomLeft',
|
||||
animate__flip: 'flip',
|
||||
animate__flipInX: 'flipInX',
|
||||
animate__flipInY: 'flipInY',
|
||||
animate__flipOutX: 'flipOutX',
|
||||
animate__flipOutY: 'flipOutY',
|
||||
animate__lightSpeedInRight: 'lightSpeedInRight',
|
||||
animate__lightSpeedInLeft: 'lightSpeedInLeft',
|
||||
animate__lightSpeedOutRight: 'lightSpeedOutRight',
|
||||
animate__lightSpeedOutLeft: 'lightSpeedOutLeft',
|
||||
animate__rotateIn: 'rotateIn',
|
||||
animate__rotateInDownLeft: 'rotateInDownLeft',
|
||||
animate__rotateInDownRight: 'rotateInDownRight',
|
||||
animate__rotateInUpLeft: 'rotateInUpLeft',
|
||||
animate__rotateInUpRight: 'rotateInUpRight',
|
||||
animate__rotateOut: 'rotateOut',
|
||||
animate__rotateOutDownLeft: 'rotateOutDownLeft',
|
||||
animate__rotateOutDownRight: 'rotateOutDownRight',
|
||||
animate__rotateOutUpLeft: 'rotateOutUpLeft',
|
||||
animate__rotateOutUpRight: 'rotateOutUpRight',
|
||||
animate__hinge: 'hinge',
|
||||
animate__jackInTheBox: 'jackInTheBox',
|
||||
animate__rollIn: 'rollIn',
|
||||
animate__rollOut: 'rollOut',
|
||||
animate__zoomIn: 'zoomIn',
|
||||
animate__zoomInDown: 'zoomInDown',
|
||||
animate__zoomInLeft: 'zoomInLeft',
|
||||
animate__zoomInRight: 'zoomInRight',
|
||||
animate__zoomInUp: 'zoomInUp',
|
||||
animate__zoomOut: 'zoomOut',
|
||||
animate__zoomOutDown: 'zoomOutDown',
|
||||
animate__zoomOutLeft: 'zoomOutLeft',
|
||||
animate__zoomOutRight: 'zoomOutRight',
|
||||
animate__zoomOutUp: 'zoomOutUp',
|
||||
animate__slideInDown: 'slideInDown',
|
||||
animate__slideInLeft: 'slideInLeft',
|
||||
animate__slideInRight: 'slideInRight',
|
||||
animate__slideInUp: 'slideInUp',
|
||||
animate__slideOutDown: 'slideOutDown',
|
||||
animate__slideOutLeft: 'slideOutLeft',
|
||||
animate__slideOutRight: 'slideOutRight',
|
||||
animate__slideOutUp: 'slideOutUp',
|
||||
};
|
||||
|
||||
const animateRepeat: Record<string, string> = {
|
||||
'': '无',
|
||||
'1': '1次',
|
||||
'2': '2次',
|
||||
'3': '3次',
|
||||
'4': '4次',
|
||||
infinite: '无限',
|
||||
};
|
||||
|
||||
const animateSpeed: Record<string, string> = {
|
||||
'': '普通',
|
||||
animate__slow: '特慢',
|
||||
animate__slower: '慢速',
|
||||
animate__fast: '快速',
|
||||
animate__faster: '特快',
|
||||
};
|
||||
|
||||
let lastAnimate = '';
|
||||
/**
|
||||
*
|
||||
* 这个控制组件配置项写死,只可能出现或者不出现
|
||||
* @return {*}
|
||||
*/
|
||||
function AnimateControl(props: AnimateControlProps) {
|
||||
const [count, setCount] = useState<number | null>(null);
|
||||
const [sign, setSign] = useState(false);
|
||||
const v1 = useMemo(() => {
|
||||
if (sign) {
|
||||
return lastAnimate;
|
||||
} else {
|
||||
const val = props.current.animate.animate
|
||||
? animateCategory[props.current.animate.animate]
|
||||
: '';
|
||||
lastAnimate = val;
|
||||
return val;
|
||||
}
|
||||
}, [props.current.animate.animate, sign]);
|
||||
|
||||
const v2 = useMemo(() => {
|
||||
if (typeof props.current.animate.animationIterationCount === 'number') {
|
||||
setCount(props.current.animate.animationIterationCount);
|
||||
return '';
|
||||
} else {
|
||||
setCount(null);
|
||||
return props.current.animate.animationIterationCount
|
||||
? animateRepeat[props.current.animate.animationIterationCount]
|
||||
: '';
|
||||
}
|
||||
}, [props.current.animate.animationIterationCount]);
|
||||
|
||||
const v3 = useMemo(() => {
|
||||
return animateSpeed[props.current.animate.speed ?? ''];
|
||||
}, [props.current.animate.speed]);
|
||||
|
||||
const changeAnimation = (
|
||||
e: any,
|
||||
props: AnimateControlProps,
|
||||
type: 'animate' | 'animationIterationCount' | 'speed'
|
||||
) => {
|
||||
if (type === 'animationIterationCount') {
|
||||
setCount(null);
|
||||
}
|
||||
|
||||
const clonedata = deepCopy(props.config.getStore().getData());
|
||||
const newblock = clonedata.block.map((v: IBlockType) => {
|
||||
if (v.id === props.current.id) {
|
||||
if (type === 'animationIterationCount') {
|
||||
v.animate[type] = Number(e);
|
||||
}
|
||||
v.animate[type] = e;
|
||||
}
|
||||
return v;
|
||||
});
|
||||
const [item] = clonedata.block.filter((item: IBlockType) => item.id === props.current.id);
|
||||
if (item?.animate?.animate) {
|
||||
const cloneNewBlock = deepCopy(newblock);
|
||||
const temporaryBlock = cloneNewBlock.map((item: IBlockType) => {
|
||||
if (item.id === props.current.id) {
|
||||
delete item.animate.animate;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
setSign(true);
|
||||
// 若有动画属性则删除动画属性再将动画属性添加
|
||||
props.config.getStore().setData({ ...clonedata, block: [...temporaryBlock] });
|
||||
}
|
||||
setTimeout(() => {
|
||||
props.config.getStore().setData({ ...clonedata, block: [...newblock] });
|
||||
setSign(false);
|
||||
});
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Row style={{ padding: '20px' }}>
|
||||
<Col span={6} style={{ lineHeight: '30px' }}>
|
||||
动画种类
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Select
|
||||
value={v1}
|
||||
onChange={(e) => changeAnimation(e, props, 'animate')}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{Object.keys(animateCategory).map((v) => {
|
||||
return (
|
||||
<Select.Option value={v} key={v}>
|
||||
{animateCategory[v]}
|
||||
</Select.Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ padding: '20px' }}>
|
||||
<Col span={6} style={{ lineHeight: '30px' }}>
|
||||
频率
|
||||
</Col>
|
||||
<Col span={18} style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<InputNumber
|
||||
min={1}
|
||||
value={count as number}
|
||||
onChange={(value) => {
|
||||
setCount(value);
|
||||
const clonedata = deepCopy(props.config.getStore().getData());
|
||||
const newblock = clonedata.block.map((v: IBlockType) => {
|
||||
if (v.id === props.current.id) {
|
||||
v.animate.animationIterationCount = value;
|
||||
}
|
||||
return v;
|
||||
});
|
||||
|
||||
const [item] = clonedata.block.filter(
|
||||
(item: IBlockType) => item.id === props.current.id
|
||||
);
|
||||
|
||||
if (item?.animate?.animate) {
|
||||
const cloneNewBlock = deepCopy(newblock);
|
||||
const temporaryBlock = cloneNewBlock.map((item: IBlockType) => {
|
||||
if (item.id === props.current.id) {
|
||||
delete item.animate.animate;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
setSign(true);
|
||||
props.config.getStore().setData({ ...clonedata, block: [...temporaryBlock] });
|
||||
}
|
||||
setTimeout(() => {
|
||||
props.config.getStore().setData({ ...clonedata, block: [...newblock] });
|
||||
setSign(false);
|
||||
});
|
||||
}}
|
||||
></InputNumber>
|
||||
<Select
|
||||
value={v2}
|
||||
onChange={(e) => changeAnimation(e, props, 'animationIterationCount')}
|
||||
style={{ width: '60%' }}
|
||||
>
|
||||
{Object.keys(animateRepeat).map((v) => {
|
||||
return (
|
||||
<Select.Option value={v} key={v}>
|
||||
{animateRepeat[v]}
|
||||
</Select.Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ padding: '20px' }}>
|
||||
<Col span={6} style={{ lineHeight: '30px' }}>
|
||||
动画速度
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Select
|
||||
value={v3}
|
||||
onChange={(e: any) => changeAnimation(e, props, 'speed')}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{Object.keys(animateSpeed).map((v) => {
|
||||
return (
|
||||
<Select.Option value={v} key={v}>
|
||||
{animateSpeed[v]}
|
||||
</Select.Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AnimateControl;
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:32:55
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 14:33:06
|
||||
* @FilePath: \visual-editor\src\plugin\formComponents\input.tsx
|
||||
*/
|
||||
import { deepCopy } from 'dooringx-lib';
|
||||
import { store } from 'dooringx-lib';
|
||||
import { Col, Input, Row } from 'antd';
|
||||
import { memo, useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import { FormMap } from '../formTypes';
|
||||
import { CreateOptionsRes } from 'dooringx-lib/dist/core/components/formTypes';
|
||||
import { IBlockType } from 'dooringx-lib/dist/core/store/storetype';
|
||||
|
||||
interface MInputProps {
|
||||
data: CreateOptionsRes<FormMap, 'input'>;
|
||||
current: IBlockType;
|
||||
}
|
||||
|
||||
function MInput(props: MInputProps) {
|
||||
const option = useMemo(() => {
|
||||
return props.data?.option || {};
|
||||
}, [props.data]);
|
||||
return (
|
||||
<Row style={{ padding: '10px 20px' }}>
|
||||
<Col span={6} style={{ lineHeight: '30px' }}>
|
||||
{(option as any)?.label || '文字'}:
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Input
|
||||
value={props.current.props[(option as any).receive] || ''}
|
||||
onChange={(e) => {
|
||||
const receive = (option as any).receive;
|
||||
const clonedata = deepCopy(store.getData());
|
||||
const newblock = clonedata.block.map((v: IBlockType) => {
|
||||
if (v.id === props.current.id) {
|
||||
v.props[receive] = e.target.value;
|
||||
}
|
||||
return v;
|
||||
});
|
||||
store.setData({ ...clonedata, block: [...newblock] });
|
||||
}}
|
||||
></Input>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(MInput);
|
21
packages/dooringx-example/src/plugin/formTypes.ts
Normal file
21
packages/dooringx-example/src/plugin/formTypes.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:31:20
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 17:21:04
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\formTypes.ts
|
||||
*/
|
||||
export interface FormBaseType {
|
||||
receive?: string;
|
||||
}
|
||||
export interface FormInputType extends FormBaseType {
|
||||
label: string;
|
||||
text: string;
|
||||
}
|
||||
export interface FormActionButtonType {}
|
||||
export interface FormAnimateControlType {}
|
||||
export interface FormMap {
|
||||
input: FormInputType;
|
||||
actionButton: FormActionButtonType;
|
||||
animateControl: FormAnimateControlType;
|
||||
}
|
10
packages/dooringx-example/src/plugin/functionMap/index.ts
Normal file
10
packages/dooringx-example/src/plugin/functionMap/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:22:51
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-09 13:52:51
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\functionMap\index.ts
|
||||
*/
|
||||
import { FunctionCenterType } from 'dooringx-lib/dist/core/functionCenter';
|
||||
|
||||
export const functionMap: FunctionCenterType = {};
|
83
packages/dooringx-example/src/plugin/index.tsx
Normal file
83
packages/dooringx-example/src/plugin/index.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-02-27 21:33:36
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 19:32:16
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\index.tsx
|
||||
*/
|
||||
|
||||
import { InitConfig } from 'dooringx-lib';
|
||||
import { LeftRegistComponentMapItem } from 'dooringx-lib/dist/core/crossDrag';
|
||||
import { ContainerOutlined, HighlightOutlined } from '@ant-design/icons';
|
||||
import commandModules from './commanderModules';
|
||||
import { functionMap } from './functionMap';
|
||||
import { Formmodules } from './formComponentModules';
|
||||
|
||||
const LeftRegistMap: LeftRegistComponentMapItem[] = [
|
||||
// build 时如果用代码分割会生成多个文件,这样就不能生成多类型文件。
|
||||
// 建议基础包全部不分割。后面插件包可以用webpack的特性,所以插件包用新脚手架制作
|
||||
// 基础包不独立出去的原因是部分左侧分类起始值最好规定住
|
||||
// {
|
||||
// type: 'xxa',
|
||||
// component: 'asyncCo',
|
||||
// img: '',
|
||||
// urlFn: () => import('./registComponents/asyncCo'),
|
||||
// displayName:'xxx'
|
||||
// },
|
||||
{
|
||||
type: 'basic',
|
||||
component: 'button',
|
||||
img: 'icon-anniu',
|
||||
displayName: '按钮',
|
||||
urlFn: () => import('./registComponents/button'),
|
||||
},
|
||||
];
|
||||
|
||||
export const defaultConfig: Partial<InitConfig> = {
|
||||
leftAllRegistMap: LeftRegistMap,
|
||||
leftRenderListCategory: [
|
||||
{
|
||||
type: 'basic',
|
||||
icon: <HighlightOutlined />,
|
||||
displayName: '基础组件',
|
||||
},
|
||||
{
|
||||
type: 'xxc',
|
||||
icon: <ContainerOutlined />,
|
||||
custom: true,
|
||||
customRender: <div>我是自定义渲染</div>,
|
||||
},
|
||||
],
|
||||
initComponentCache: {},
|
||||
rightRenderListCategory: [
|
||||
{
|
||||
type: 'style',
|
||||
icon: (
|
||||
<div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}>
|
||||
外观
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'animate',
|
||||
icon: (
|
||||
<div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}>
|
||||
动画
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'actions',
|
||||
icon: (
|
||||
<div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}>
|
||||
事件
|
||||
</div>
|
||||
),
|
||||
},
|
||||
],
|
||||
initFunctionMap: functionMap,
|
||||
initCommandModule: commandModules,
|
||||
initFormComponents: Formmodules,
|
||||
};
|
||||
|
||||
export default defaultConfig;
|
138
packages/dooringx-example/src/plugin/registComponents/button.tsx
Normal file
138
packages/dooringx-example/src/plugin/registComponents/button.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-07 14:35:38
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 19:04:05
|
||||
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\registComponents\button.tsx
|
||||
*/
|
||||
|
||||
import { Button } from 'antd';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
changeUserValue,
|
||||
ComponentItemFactory,
|
||||
createPannelOptions,
|
||||
useDynamicAddEventCenter,
|
||||
} from 'dooringx-lib';
|
||||
import { FormMap } from '../formTypes';
|
||||
import { ComponentRenderConfigProps } from 'dooringx-lib/dist/core/components/componentItem';
|
||||
|
||||
function ButtonTemp(pr: ComponentRenderConfigProps) {
|
||||
const props = pr.data.props;
|
||||
const eventCenter = useMemo(() => {
|
||||
return pr.config.getEventCenter();
|
||||
}, [pr.config]);
|
||||
|
||||
useDynamicAddEventCenter(pr, `${pr.data.id}-init`, '初始渲染时机'); //注册名必须带id 约定!
|
||||
useDynamicAddEventCenter(pr, `${pr.data.id}-click`, '点击执行时机');
|
||||
|
||||
useEffect(() => {
|
||||
// 模拟抛出事件
|
||||
if (pr.context === 'preview') {
|
||||
eventCenter.runEventQueue(`${pr.data.id}-init`, pr.config);
|
||||
}
|
||||
}, [eventCenter, pr.config, pr.context, pr.data.id]);
|
||||
|
||||
const [text, setText] = useState('');
|
||||
useEffect(() => {
|
||||
//模拟改变文本
|
||||
const functionCenter = eventCenter.getFunctionCenter();
|
||||
const unregist = functionCenter.register(
|
||||
`${pr.data.id}+改变文本函数`,
|
||||
async (ctx, next, config, args: any, _eventList, iname) => {
|
||||
const userSelect = iname.data;
|
||||
const ctxVal = changeUserValue(
|
||||
userSelect['改变文本数据源'],
|
||||
args,
|
||||
'_changeval',
|
||||
config,
|
||||
ctx
|
||||
);
|
||||
const text = ctxVal[0];
|
||||
setText(text);
|
||||
next();
|
||||
},
|
||||
[
|
||||
{
|
||||
name: '改变文本数据源',
|
||||
data: ['ctx', 'input', 'dataSource'],
|
||||
options: {
|
||||
receive: '_changeval',
|
||||
multi: false,
|
||||
},
|
||||
},
|
||||
]
|
||||
);
|
||||
return () => {
|
||||
unregist();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Button
|
||||
style={{
|
||||
width: pr.data.width ? pr.data.width : props.sizeData[0],
|
||||
height: pr.data.height ? pr.data.height : props.sizeData[1],
|
||||
borderRadius: props.borderRadius + 'px',
|
||||
border: `${props.borderData.borderWidth}px ${props.borderData.borderStyle} ${props.borderData.borderColor}`,
|
||||
backgroundColor: props.backgroundColor,
|
||||
color: props.fontData.color,
|
||||
fontSize: props.fontData.fontSize,
|
||||
fontWeight: props.fontData.fontWeight,
|
||||
fontStyle: props.fontData.fontStyle,
|
||||
textDecoration: props.fontData.textDecoration,
|
||||
lineHeight: props.lineHeight,
|
||||
}}
|
||||
onClick={() => {
|
||||
eventCenter.runEventQueue(`${pr.data.id}-click`, pr.config);
|
||||
}}
|
||||
// type={props.type}
|
||||
// size={props.size}
|
||||
>
|
||||
{text ? text : props.text}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
const MButton = new ComponentItemFactory(
|
||||
'button',
|
||||
'按钮',
|
||||
{
|
||||
style: [
|
||||
createPannelOptions<FormMap, 'input'>('input', {
|
||||
receive: 'text', //用于发送回的props,必传 ,跨组件传递需要指定额外字段
|
||||
label: '文字',
|
||||
text: 'yehuozhili',
|
||||
}),
|
||||
],
|
||||
animate: [createPannelOptions<FormMap, 'animateControl'>('animateControl', {})],
|
||||
actions: [createPannelOptions<FormMap, 'actionButton'>('actionButton', {})],
|
||||
},
|
||||
{
|
||||
props: {
|
||||
text: 'yehuozhili',
|
||||
sizeData: [100, 30],
|
||||
backgroundColor: 'rgba(0,132,255,1)',
|
||||
lineHeight: 1,
|
||||
borderRadius: 0,
|
||||
borderData: {
|
||||
borderWidth: 0,
|
||||
borderColor: 'rgba(0,0,0,1)',
|
||||
borderStyle: 'solid',
|
||||
},
|
||||
fontData: {
|
||||
fontSize: 14,
|
||||
textDecoration: 'none',
|
||||
fontStyle: 'normal',
|
||||
color: 'rgba(255,255,255,1)',
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
},
|
||||
},
|
||||
(data, context, store, config) => {
|
||||
return <ButtonTemp data={data} store={store} context={context} config={config}></ButtonTemp>;
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
export default MButton;
|
30
packages/dooringx-example/tsconfig.json
Normal file
30
packages/dooringx-example/tsconfig.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"jsx": "react-jsx",
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": "./",
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"@@/*": ["src/.umi/*"]
|
||||
},
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["mock/**/*", "src/**/*", "config/**/*", ".umirc.ts", "typings.d.ts"],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"lib",
|
||||
"es",
|
||||
"dist",
|
||||
"typings",
|
||||
"**/__test__",
|
||||
"test",
|
||||
"docs",
|
||||
"tests"
|
||||
]
|
||||
}
|
8
packages/dooringx-example/typings.d.ts
vendored
Normal file
8
packages/dooringx-example/typings.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
declare module '*.css';
|
||||
declare module '*.less';
|
||||
declare module '*.png';
|
||||
declare module '*.svg' {
|
||||
export function ReactComponent(props: React.SVGProps<SVGSVGElement>): React.ReactElement;
|
||||
const url: string;
|
||||
export default url;
|
||||
}
|
@@ -2,15 +2,16 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-01-31 20:44:16
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-08 20:44:20
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\README.md
|
||||
* @LastEditTime: 2021-07-10 18:07:00
|
||||
* @FilePath: \dooringx\packages\dooringx-lib\README.md
|
||||
-->
|
||||
|
||||
## DooringX 核心包
|
||||
|
||||
## Dooringx-lib
|
||||
## changelog
|
||||
|
||||
- 0.1.7 修改预览特殊条件显示,删除 console
|
||||
- 0.1.9 增加全局body设置
|
||||
- 0.1.8 增加弹窗设置,移除modalContainer
|
||||
- 0.1.7 修改预览特殊条件显示,删除console
|
||||
- 0.1.6 调整初始缩放,画布初始比例,增加回正画布功能。
|
||||
- 0.1.5 删除未作按钮,增加 fixed 配置
|
||||
- 0.1.5 删除未作按钮,增加fixed配置
|
||||
- 0.1.4 基础功能
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"version": "0.1.7",
|
||||
"version": "0.1.9",
|
||||
"license": "MIT",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/dooringx-lib.esm.js",
|
||||
"browser": "dist/dooringx-lib.esm.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
@@ -20,7 +18,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8",
|
||||
"antd": ">=4"
|
||||
"antd": ">=4",
|
||||
"animate.css": ">=4"
|
||||
},
|
||||
"name": "dooringx-lib",
|
||||
"author": "yehuozhili",
|
||||
@@ -46,7 +45,6 @@
|
||||
"deepcopy": "^2.1.0",
|
||||
"react-color": "^2.19.3",
|
||||
"react-sortable-hoc": "^2.0.0",
|
||||
"uuid": "^8.3.2",
|
||||
"animate.css": "^4.1.1"
|
||||
"uuid": "^8.3.2"
|
||||
}
|
||||
}
|
||||
|
@@ -39,7 +39,6 @@ function Container(props: PropsWithChildren<ContainerProps>) {
|
||||
return props.state.globalState.containerColor;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.context === 'edit' && (
|
||||
|
@@ -2,8 +2,8 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-02-04 10:32:45
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-06 23:55:37
|
||||
* @FilePath: \dooringv2\packages\dooring-v2-lib\src\components\leftConfig.tsx
|
||||
* @LastEditTime: 2021-07-10 15:47:34
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\src\components\leftConfig.tsx
|
||||
*/
|
||||
import React, { ReactNode, useEffect, useMemo, useState } from 'react';
|
||||
import { Input, Menu } from 'antd';
|
||||
@@ -42,7 +42,7 @@ function LeftConfig(props: LeftConfigProps) {
|
||||
cache = config.leftAllRegistMap.filter((k) => k.type === type);
|
||||
cache.forEach((v) => props.config.asyncRegistComponent(v.component));
|
||||
setLeftRender(
|
||||
<div className={styles.leftco}>
|
||||
<div className={`${styles.leftco} yh-leftcomp`}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
@@ -53,7 +53,7 @@ function LeftConfig(props: LeftConfigProps) {
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: 100,
|
||||
width: 120,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
|
@@ -29,6 +29,8 @@ export function ModalRender(props: ModalRenderProps) {
|
||||
}, [props.data.modalMap, props.name]);
|
||||
const { parentDom, rootDom } = props;
|
||||
|
||||
const modalConfig = props.data.modalConfig[props.name];
|
||||
|
||||
//这里还要添加个关闭函数,
|
||||
const unmount = useMemo(() => {
|
||||
return () => {
|
||||
@@ -58,7 +60,9 @@ export function ModalRender(props: ModalRenderProps) {
|
||||
})}
|
||||
<div
|
||||
onClick={() => {
|
||||
unmount();
|
||||
if (!modalConfig) {
|
||||
unmount();
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
backgroundColor: '#716f6f9e',
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-03-14 05:40:37
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-08 20:44:45
|
||||
* @LastEditTime: 2021-07-10 16:09:19
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\src\components\preview.tsx
|
||||
*/
|
||||
import Container from './container';
|
||||
@@ -24,6 +24,12 @@ function Preview(props: { config: UserConfig; loadText?: ReactNode }): ReactElem
|
||||
.getEventCenter()
|
||||
.syncEventMap(props.config.getStore().getData(), props.config.getStoreChanger());
|
||||
setTimeout(() => {
|
||||
// 设置全局
|
||||
const bodyColor = props.config.getStore().getData().globalState?.bodyColor;
|
||||
if (bodyColor) {
|
||||
document.body.style.backgroundColor = bodyColor;
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
});
|
||||
}, [props.config]);
|
||||
|
@@ -2,15 +2,15 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-03-14 05:42:13
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-05 23:35:05
|
||||
* @FilePath: \DooringV2\packages\dooring-v2-lib\src\components\rightConfig.tsx
|
||||
* @LastEditTime: 2021-07-10 16:06:33
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\src\components\rightConfig.tsx
|
||||
*/
|
||||
import { CreateOptionsRes } from '../core/components/formTypes';
|
||||
import { IBlockType, IStoreData } from '../core/store/storetype';
|
||||
import { store } from '../runtime/store';
|
||||
import { PropsWithChildren, useEffect, useMemo, useState } from 'react';
|
||||
import React from 'react';
|
||||
import { Tabs, Input, Row, Col } from 'antd';
|
||||
import { Tabs, Input, Row, Col, Checkbox } from 'antd';
|
||||
import UserConfig from '../config';
|
||||
import { RGBColor, SketchPicker } from 'react-color';
|
||||
import { rgba2Obj } from '../core/utils';
|
||||
@@ -89,8 +89,15 @@ function RightConfig(props: PropsWithChildren<RightConfigProps>) {
|
||||
? rgba2Obj(props.config.getStoreChanger().getOrigin()?.now.globalState.containerColor)
|
||||
: rgba2Obj(props.config.getStore().getData().globalState.containerColor);
|
||||
}, [props.config]);
|
||||
const initColor2 = useMemo(() => {
|
||||
return props.config.getStoreChanger().isEdit()
|
||||
? rgba2Obj(props.config.getStoreChanger().getOrigin()?.now.globalState.bodyColor)
|
||||
: rgba2Obj(props.config.getStore().getData().globalState.bodyColor);
|
||||
}, [props.config]);
|
||||
const [color, setColor] = useState<RGBColor>(initColor);
|
||||
const [color2, setColor2] = useState<RGBColor>(initColor2);
|
||||
const [colorPickerVisible, setColorPickerVisible] = useState(false);
|
||||
const [colorPickerVisible2, setColorPickerVisible2] = useState(false);
|
||||
const initTitle = useMemo(() => {
|
||||
const title = props.config.getStoreChanger().isEdit()
|
||||
? props.config.getStoreChanger().getOrigin()?.now.globalState.title
|
||||
@@ -100,6 +107,9 @@ function RightConfig(props: PropsWithChildren<RightConfigProps>) {
|
||||
const [title, setTitle] = useState(initTitle);
|
||||
|
||||
const customGlobal = props.config.getConfig().rightGlobalCustom;
|
||||
const isEdit = props.config.getStoreChanger().isEdit();
|
||||
const modalName = props.config.getStoreChanger().getState().modalEditName;
|
||||
const originData = props.config.getStoreChanger().getOrigin()?.now;
|
||||
return (
|
||||
<div
|
||||
className="ant-menu"
|
||||
@@ -137,7 +147,7 @@ function RightConfig(props: PropsWithChildren<RightConfigProps>) {
|
||||
})}
|
||||
</Tabs>
|
||||
)}
|
||||
{!current && !customGlobal && (
|
||||
{!current && !isEdit && !customGlobal && (
|
||||
<div style={{ padding: '20px' }}>
|
||||
<Row style={{ padding: '10 0 20px 0', fontWeight: 'bold' }}>全局设置</Row>
|
||||
<Row style={{ padding: '10px 0' }}>
|
||||
@@ -230,9 +240,97 @@ function RightConfig(props: PropsWithChildren<RightConfigProps>) {
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ padding: '10px 0' }}>
|
||||
<Col span={6}>body底色</Col>
|
||||
<Col span={18}>
|
||||
{
|
||||
<div style={{ position: 'relative' }}>
|
||||
<div
|
||||
onClick={() => {
|
||||
setColorPickerVisible2((pre) => !pre);
|
||||
}}
|
||||
style={{
|
||||
background: '#fff',
|
||||
borderRadius: '1px',
|
||||
boxShadow: '0 0 0 1px rgba(0,0,0,.1)',
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
borderRadius: '2px',
|
||||
background: `rgba(${color2.r}, ${color2.g}, ${color2.b}, ${color2.a})`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{colorPickerVisible2 && (
|
||||
<>
|
||||
<div style={{ position: 'absolute', zIndex: 2000 }}>
|
||||
<SketchPicker
|
||||
color={color2}
|
||||
onChange={(c) => {
|
||||
const newcolor = c.rgb;
|
||||
setColor2(newcolor);
|
||||
const isEdit = props.config.getStoreChanger().isEdit();
|
||||
if (isEdit) {
|
||||
const originData: IStoreData = deepcopy(
|
||||
props.config.getStoreChanger().getOrigin()!.now
|
||||
);
|
||||
originData.globalState.bodyColor = `rgba(${newcolor.r}, ${newcolor.g}, ${newcolor.b}, ${newcolor.a})`;
|
||||
props.config.getStoreChanger().updateOrigin(originData);
|
||||
} else {
|
||||
const originData = deepcopy(props.config.getStore().getData());
|
||||
originData.globalState.bodyColor = `rgba(${newcolor.r}, ${newcolor.g}, ${newcolor.b}, ${newcolor.a})`;
|
||||
props.config.getStore().setData(originData);
|
||||
}
|
||||
}}
|
||||
></SketchPicker>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
top: '0px',
|
||||
right: '0px',
|
||||
bottom: '0px',
|
||||
left: '0px',
|
||||
zIndex: 1000,
|
||||
}}
|
||||
onClick={() => setColorPickerVisible2(false)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)}
|
||||
{!current && !isEdit && customGlobal && customGlobal}
|
||||
{!current && isEdit && (
|
||||
<div style={{ padding: '20px' }} className="yh-tcsz">
|
||||
<Row style={{ padding: '10 0 20px 0', fontWeight: 'bold' }}>弹窗设置</Row>
|
||||
<Row style={{ padding: '10px 0' }}>
|
||||
<Col span={8}>取消点击删除弹窗</Col>
|
||||
<Col span={16} style={{ textAlign: 'right' }}>
|
||||
<Checkbox
|
||||
checked={originData ? originData.modalConfig[modalName] : false}
|
||||
onChange={(e) => {
|
||||
const val = e.target.checked;
|
||||
const cloneData = deepcopy(originData);
|
||||
if (cloneData) {
|
||||
cloneData.modalConfig[modalName] = val;
|
||||
props.config.getStoreChanger().updateOrigin(cloneData);
|
||||
props.config.getStore().forceUpdate();
|
||||
}
|
||||
}}
|
||||
></Checkbox>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)}
|
||||
{!current && customGlobal && customGlobal}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -2,8 +2,8 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-02-25 21:16:58
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-08 20:42:22
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\src\config\index.tsx
|
||||
* @LastEditTime: 2021-07-10 18:29:07
|
||||
* @FilePath: \dooringx\packages\dooringx-lib\src\config\index.tsx
|
||||
*/
|
||||
import { IBlockType, IStoreData } from '../core/store/storetype';
|
||||
import { store } from '../runtime/store';
|
||||
@@ -23,7 +23,6 @@ import { createModal, unmountMap } from '../components/modalRender';
|
||||
import { scaleState } from '../core/scale/state';
|
||||
import { CommanderItemFactory } from '../core/command/abstract';
|
||||
import MmodalMask from '../core/components/defaultFormComponents/modalMask';
|
||||
import MmodalContainer from '../core/components/defaultFormComponents/modalContainer';
|
||||
|
||||
// 组件部分
|
||||
|
||||
@@ -156,7 +155,9 @@ export const defaultStore: IStoreData = {
|
||||
globalState: {
|
||||
containerColor: 'rgba(255,255,255,1)',
|
||||
title: 'dooring',
|
||||
bodyColor: 'rgba(255,255,255,1)',
|
||||
},
|
||||
modalConfig: {},
|
||||
};
|
||||
|
||||
export const defaultConfig: InitConfig = {
|
||||
@@ -166,8 +167,7 @@ export const defaultConfig: InitConfig = {
|
||||
rightGlobalCustom: null,
|
||||
rightRenderListCategory: [],
|
||||
initComponentCache: {
|
||||
modalMask: { component: MmodalMask }, // 这2个组件不配置显示
|
||||
modalContainer: { component: MmodalContainer },
|
||||
modalMask: { component: MmodalMask }, // 这个组件不配置显示
|
||||
},
|
||||
initFunctionMap: {
|
||||
打开弹窗函数: {
|
||||
@@ -192,7 +192,9 @@ export const defaultConfig: InitConfig = {
|
||||
fn: (_ctx, next, _config, args) => {
|
||||
const modalName = args['_modal'];
|
||||
const fn = unmountMap.get(modalName);
|
||||
fn ? fn() : '';
|
||||
if (fn) {
|
||||
fn();
|
||||
}
|
||||
next();
|
||||
},
|
||||
config: [
|
||||
|
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-04-05 19:21:36
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-05 23:56:07
|
||||
* @FilePath: \DooringV2\packages\dooring-v2-lib\src\core\components\defaultFormComponents\modalContainer.tsx
|
||||
*/
|
||||
import React from 'react';
|
||||
import { ComponentItemFactory } from '../abstract';
|
||||
|
||||
const MmodalContainer = new ComponentItemFactory(
|
||||
'modalContainer',
|
||||
'模态框容器',
|
||||
{},
|
||||
{
|
||||
props: {},
|
||||
width: 300,
|
||||
height: 300,
|
||||
},
|
||||
(data) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
zIndex: data.zIndex,
|
||||
width: data.width,
|
||||
height: data.height,
|
||||
backgroundColor: 'white',
|
||||
}}
|
||||
></div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default MmodalContainer;
|
@@ -2,8 +2,8 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-03-14 04:29:09
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-03-14 04:43:53
|
||||
* @FilePath: \dooring-v2\src\core\components\index.ts
|
||||
* @LastEditTime: 2021-07-10 18:34:34
|
||||
* @FilePath: \dooringx\packages\dooringx-lib\src\core\components\index.ts
|
||||
*/
|
||||
import { ComponentItem } from './componentItem';
|
||||
|
||||
|
@@ -2,8 +2,8 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-03-14 04:29:09
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-04 15:21:54
|
||||
* @FilePath: \DooringV2\packages\dooring-v2-lib\src\core\crossDrag\index.ts
|
||||
* @LastEditTime: 2021-07-10 18:34:40
|
||||
* @FilePath: \dooringx\packages\dooringx-lib\src\core\crossDrag\index.ts
|
||||
*/
|
||||
import { store } from '../../runtime/store';
|
||||
import { componentRegister } from '../../runtime';
|
||||
|
@@ -2,8 +2,8 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-04-06 19:33:17
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-04 14:41:48
|
||||
* @FilePath: \DooringV2\packages\dooring-v2-lib\src\core\eventCenter\index.ts
|
||||
* @LastEditTime: 2021-07-09 16:33:22
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\src\core\eventCenter\index.ts
|
||||
*/
|
||||
import UserConfig from '../../config';
|
||||
import { FunctionCenter, FunctionCenterType } from '../functionCenter';
|
||||
|
@@ -2,8 +2,8 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-04-08 19:59:01
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 01:46:17
|
||||
* @FilePath: \dooringv2\packages\dooringx-lib\src\core\functionCenter\index.ts
|
||||
* @LastEditTime: 2021-07-09 16:23:02
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\src\core\functionCenter\index.ts
|
||||
*/
|
||||
|
||||
import UserConfig from '../../config';
|
||||
@@ -83,6 +83,17 @@ export class FunctionCenter {
|
||||
return this.configMap;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 删除的组件需要删除动态注册的函数
|
||||
* @param {string} name
|
||||
* @memberof FunctionCenter
|
||||
*/
|
||||
deleteFunc(name: string) {
|
||||
delete this.funcitonMap[name];
|
||||
delete this.configMap[name];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 注册函数,同名覆盖,返回删除函数
|
||||
|
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-03-14 04:29:09
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @LastEditTime: 2021-06-19 17:07:10
|
||||
* @FilePath: \dooringv2\packages\dooring-v2-lib\src\core\store\index.ts
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 18:17:56
|
||||
* @FilePath: \dooringx\packages\dooringx-lib\src\core\store\index.ts
|
||||
*/
|
||||
import { IStoreData } from './storetype';
|
||||
import { storeChangerState } from '../storeChanger/state';
|
||||
@@ -17,9 +17,11 @@ export const initialData: IStoreData = {
|
||||
modalMap: {},
|
||||
dataSource: {},
|
||||
globalState: {},
|
||||
modalConfig: {},
|
||||
};
|
||||
|
||||
class Store {
|
||||
static instance: Store;
|
||||
constructor(
|
||||
public storeDataList: IStoreData[] = [initialData],
|
||||
public listeners: Array<Function> = [],
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-03-14 04:29:09
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 17:00:07
|
||||
* @LastEditTime: 2021-07-09 17:22:14
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\src\core\store\storetype.ts
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface IStoreData {
|
||||
modalMap: Record<string, IStoreData>;
|
||||
dataSource: Record<string, any>;
|
||||
globalState: Record<string, any>;
|
||||
modalConfig: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface IBlockType {
|
||||
@@ -38,7 +39,7 @@ export interface IBlockType {
|
||||
functionList: Array<string>; //抛出的函数名
|
||||
animate: {
|
||||
animate?: string; //动画名
|
||||
animationIterationCount?: any;
|
||||
animationIterationCount?: number | string;
|
||||
speed?: //动画速度
|
||||
'animate__slow' | 'animate__slower' | 'animate__fast' | 'animate__faster' | '';
|
||||
delay?: //首次延迟
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-04-05 14:55:31
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-07 16:59:54
|
||||
* @LastEditTime: 2021-07-09 18:31:24
|
||||
* @FilePath: \DooringV2\packages\dooringx-lib\src\core\storeChanger\index.ts
|
||||
*/
|
||||
|
||||
@@ -43,26 +43,6 @@ function createDefaultModalBlock(): IStoreData['block'] {
|
||||
animate: {},
|
||||
fixed: false,
|
||||
},
|
||||
{
|
||||
id: createUid('modal-container'),
|
||||
name: 'modalContainer',
|
||||
top: 100,
|
||||
left: 35,
|
||||
zIndex: 0,
|
||||
props: {},
|
||||
resize: true,
|
||||
focus: true,
|
||||
position: 'absolute',
|
||||
display: 'block',
|
||||
width: 300,
|
||||
height: 300,
|
||||
syncList: [],
|
||||
canDrag: true,
|
||||
eventMap: {},
|
||||
functionList: [],
|
||||
animate: {},
|
||||
fixed: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -80,6 +60,7 @@ const defaultModalStore: () => IStoreData = () => {
|
||||
modalMap: {},
|
||||
dataSource: {},
|
||||
globalState: {},
|
||||
modalConfig: {},
|
||||
};
|
||||
};
|
||||
|
||||
|
@@ -1,7 +1,14 @@
|
||||
/*
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-07-10 16:52:41
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-10 18:28:18
|
||||
* @FilePath: \dooringx\packages\dooringx-lib\src\core\utils\icon.ts
|
||||
*/
|
||||
import { createFromIconfontCN } from '@ant-design/icons';
|
||||
|
||||
export const IconFont = createFromIconfontCN({
|
||||
scriptUrl: '//at.alicdn.com/t/font_2607370_myr2zkz3ku.js', // 在 iconfont.cn 上生成
|
||||
scriptUrl: '//at.alicdn.com/t/font_2607370_zx7pglxj1m.js', // 在 iconfont.cn 上生成
|
||||
extraCommonProps: {
|
||||
fill: 'currentColor',
|
||||
stroke: 'currentColor',
|
||||
|
@@ -156,7 +156,7 @@ export const changeLayer = (store: Store, id: string, action: 'up' | 'down' | 'd
|
||||
* @param {*} from
|
||||
* @param {*} to
|
||||
*/
|
||||
export const arrayMove = (array: any, from: number, to: number) => {
|
||||
export const arrayMove = (array: Array<any>, from: number, to: number) => {
|
||||
array = [...array];
|
||||
arrayMoveMutate(array, from, to);
|
||||
return array;
|
||||
@@ -179,7 +179,7 @@ const indexSub = (arrLength: number, toIndex: number) => {
|
||||
* @param {Number} to Index of where to move the item. If negative, it will begin that many elements from the end / 0 / -1 / 2
|
||||
* returns A new array with the item moved to the new position [1,2,3] -> [1,3,2]
|
||||
*/
|
||||
const arrayMoveMutate = (array: [], from: number, to: number) => {
|
||||
const arrayMoveMutate = (array: Array<any>, from: number, to: number) => {
|
||||
const arrLength = array.length;
|
||||
const startIndex = indexSub(arrLength, from);
|
||||
if (startIndex >= 0 && startIndex < arrLength) {
|
||||
|
@@ -2,10 +2,9 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-03-14 05:35:15
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-07-04 17:52:02
|
||||
* @FilePath: \DooringV2\packages\dooring-v2-lib\src\hooks\index.ts
|
||||
* @LastEditTime: 2021-07-10 17:46:26
|
||||
* @FilePath: \dooringx\packages\dooringx-lib\src\hooks\index.ts
|
||||
*/
|
||||
import { store } from '../runtime/store';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import UserConfig from '../config';
|
||||
import { ComponentRenderConfigProps } from '../core/components/componentItem';
|
||||
@@ -16,11 +15,13 @@ export function useStoreState(
|
||||
extraFn: Function = () => {},
|
||||
everyFn: Function = () => {}
|
||||
) {
|
||||
const store = config.getStore();
|
||||
const [state, setState] = useState(store.getData());
|
||||
const forceUpdate = useState(0)[1];
|
||||
useEffect(() => {
|
||||
const unRegister = store.subscribe(() => {
|
||||
setState(store.getData());
|
||||
const data = store.getData();
|
||||
setState(data);
|
||||
config.getEventCenter().syncEventMap(store.getData(), config.getStoreChanger());
|
||||
extraFn();
|
||||
});
|
||||
@@ -32,7 +33,7 @@ export function useStoreState(
|
||||
unRegister();
|
||||
unRegistCommandFn(commandModules, commander);
|
||||
};
|
||||
}, [config, extraFn]);
|
||||
}, [config, extraFn, forceUpdate, store]);
|
||||
useEffect(() => {
|
||||
everyFn();
|
||||
}, [everyFn]);
|
||||
|
@@ -2,15 +2,14 @@
|
||||
* @Author: yehuozhili
|
||||
* @Date: 2021-03-14 04:33:52
|
||||
* @LastEditors: yehuozhili
|
||||
* @LastEditTime: 2021-05-30 15:51:50
|
||||
* @FilePath: \dooringv2\packages\dooring-v2-lib\src\runtime\index.ts
|
||||
* @LastEditTime: 2021-07-10 18:18:15
|
||||
* @FilePath: \dooringx\packages\dooringx-lib\src\runtime\index.ts
|
||||
*/
|
||||
import CommanderWrapper from '../core/command';
|
||||
import ComponentRegister from '../core/components';
|
||||
import { FormComponentRegister } from '../core/components/formComponentRegister';
|
||||
import { StoreChanger } from '../core/storeChanger';
|
||||
import { store } from './store';
|
||||
|
||||
export const commander = new CommanderWrapper(store);
|
||||
export const componentRegister = new ComponentRegister();
|
||||
export const formRegister = new FormComponentRegister();
|
||||
|
Reference in New Issue
Block a user