vue-willtable
Version:
An editable table component for Vue
343 lines (310 loc) • 9.97 kB
Markdown
# 快速上手
完整操作示例的工作区主要由菜单、画布以及表单弹窗三部分构成。组件自带菜单与画布,表单弹窗样式与内部表单由使用方自定义。代码示例如下:
[POPE 运营操作代码示例](http://git.xiaojukeji.com/global-fe/marketing-group/open-source/strategyjs/tree/master/example/pages/pope)
[普通事件流代码示例](http://git.xiaojukeji.com/global-fe/marketing-group/open-source/strategyjs/tree/master/example/pages/common)
如果只需流程图展示,只定义节点以及数据渲染画布即可。代理示例如下:
[数据库运行代码示例](http://git.xiaojukeji.com/global-fe/marketing-group/open-source/strategyjs/tree/master/example/pages/readonly)
[发布流水线代码示例](http://git.xiaojukeji.com/global-fe/marketing-group/open-source/strategyjs/tree/master/example/pages/pipeline)
## 1. 定义菜单数据
具体参数见 [节点菜单属性](/api/attributes.html#节点菜单属性)
```javascript
import React from "react";
import { uuid } from "@didi/strategy";
import { Form, Input, Select, Button } from "antd";
import { CopyOutlined, DeleteOutlined } from "@ant-design/icons";
export const menuList = [
{
menu: "triggers",
name: "用户事件",
nodeKey: "userEvent",
nodeType: "multi",
icon: "icon-pope pope-Submit",
iconBgColor: "#5BB357",
nodeBusType: "trigger",
defaultPaths: [
{
name: "Path 1",
},
],
renderForm: (props) => {
const { form } = props;
return (
<Form {...props}>
<Form.Item shouldUpdate>
{({ getFieldValue }) => {
const paths = getFieldValue("paths");
return (
<>
{(paths || []).map((path, index) => (
<div className="mulit-path-item" key={path.key}>
<p className="mulit-path-item-header">Path {index + 1}</p>
<div className="actions">
<Button
icon={
<CopyOutlined
onClick={() => {
form.setFieldsValue({
paths: [
...paths,
{ key: uuid.v4(), name: "", data: null },
],
});
}}
/>
}
/>
{paths.length > 1 && (
<Button
icon={<DeleteOutlined />}
onClick={() => {
form.setFieldsValue({
paths: paths.filter((v) => v.key !== path.key),
});
}}
/>
)}
</div>
<Form.Item noStyle name={["paths", index, "key"]}>
<span />
</Form.Item>
<Form.Item
name={["paths", index, "name"]}
rules={[{ required: true, message: "请输入名称" }]}
>
<Input placeholder="请输入" />
</Form.Item>
<Form.Item
name={["paths", index, "data", "type"]}
rules={[{ required: true, message: "请选择类型" }]}
>
<Select
placeholder="请选择"
getPopupContainer={(e) => e.parentNode}
>
<Select.Option value="bubble" key="bubble">
冒泡
</Select.Option>
<Select.Option
value="finish_order"
key="finish_order"
>
完单
</Select.Option>
</Select>
</Form.Item>
</div>
))}
</>
);
}}
</Form.Item>
<div>
<Button
block
onClick={() => {
const paths = form.getFieldValue("paths") || [];
form.setFieldsValue({ paths: [...paths, { key: uuid.v4() }] });
}}
>
Add Path
</Button>
</div>
</Form>
);
},
},
];
```
## 2. 编写表单弹窗
根据 `nodeClick` 获取当前触发点击的节点,表单弹窗动态渲染不同表单
```javascript
import React from "react";
import { Form, message } from "antd";
const Drawer = (props) => {
const { currentNode, setCurrentNode, saveNodeData } = props;
const [formRef] = Form.useForm();
const FormCom = currentNode?.renderForm;
React.useEffect(() => {
formRef.resetFields();
if (currentNode) {
if (currentNode.nodeType === "multi") {
formRef.setFieldsValue(currentNode);
} else {
formRef.setFieldsValue(currentNode.nodeDetail);
}
}
}, [currentNode, formRef]);
return (
<div className="strategy-drawer" style={{ right: currentNode ? 0 : -400 }}>
<div className="strategy-drawer-header">
<div className="strategy-drawer-title">{currentNode?.name}</div>
<i
className="icon-pope pope-Close"
onClick={() => {
setCurrentNode(null);
}}
/>
</div>
{FormCom && <FormCom labelCol={{ span: 24 }} form={formRef} />}
<div className="strategy-drawer-footer">
<div
className="strategy-button"
onClick={() => {
formRef
.validateFields()
.then((res) => {
if (currentNode) {
if (currentNode.nodeType === "normal") {
currentNode.nodeDetail = res;
}
if (currentNode.nodeType === "multi") {
Object.keys(res).forEach((key) => {
currentNode[key] = res[key];
});
}
}
saveNodeData(currentNode);
setCurrentNode(null);
})
.catch((err) => {
if (err.errorFields) {
err.errorFields.map((item) =>
message.error(item.errors?.join(","))
);
}
});
}}
>
Done
</div>
</div>
</div>
);
};
export default Drawer;
```
## 3. 使用组件
获取初始数据、设置数据、传入菜单列表数据以及传入相应的回调方法
```javascript
import React, { useRef } from "react";
import "@didi/strategy/dist/strategy.css";
import { StrategyEditor, uuid } from "@didi/strategy";
import { menuList } from "./menuList";
const App = () => {
const strategyRef = useRef(null);
const [currentNode, setCurrentNode] = React.useState(null);
const nodeClick = (node) => {
setCurrentNode(node);
};
React.useEffect(() => {
// 获取初始数据
const data: StrategyMetadata = {
nodeMap: {
"00": {
nodeId: "00",
nodeKey: "group",
nodeType: NodeType.normal,
nodeBusType: "common",
nodeDetail: {
id: "123456",
},
},
"01": {
nodeId: "01",
nodeKey: "userEvent",
nodeType: NodeType.multi,
nodeBusType: "trigger",
paths: [
{
key: "01",
name: "冒泡",
data: {
type: "bubble",
},
},
{
key: "02",
name: "完单",
data: {
type: "finish_order",
},
},
],
},
"02": {
nodeId: "02",
nodeKey: "userAttr",
nodeBusType: "condition",
nodeType: NodeType.multi,
paths: [
{
key: "03",
name: "数量大于1",
data: {
type: "amount",
},
},
],
},
"03": {
nodeId: "03",
nodeKey: "coupon",
nodeBusType: "action",
nodeType: NodeType.normal,
nodeDetail: {
content: "ddd",
},
},
"04": {
nodeId: "04",
nodeKey: "placeholder",
nodeType: NodeType.placeholder,
},
},
edgeMap: {
"00": {
edgeId: "00",
startNodeId: "00",
endNodeId: "01",
},
"01": {
edgeId: "01",
edgeName: "冒泡",
startNodeId: "01",
endNodeId: "02",
},
"02": {
edgeId: "02",
edgeName: "完单",
startNodeId: "01",
endNodeId: "04",
},
"03": {
edgeId: "03",
edgeName: "数量大于1",
startNodeId: "02",
endNodeId: "03",
},
},
};
// 设置画布数据
strategyRef.current?.setData(data);
}, []);
return (
<div className="app">
<StrategyEditor
editorStyle={{ height: "calc(100% - 50px)" }}
ref={strategyRef}
NodeMenuList={NodeMenuList}
nodeClick={nodeClick}
/>
<Drawer
currentNode={currentNode}
setCurrentNode={setCurrentNode}
saveNodeData={strategyRef.current.saveNodeData}
/>
</div>
);
};
export default App;
```