├── .editorconfig
├── .env
├── .eslintrc
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .storybook
├── config.js
└── webpack.config.js
├── .svn
├── entries
├── format
├── pristine
│ ├── 10
│ │ └── 1001f16043056312d6e6bb7ec5dfdf0e55cd2eee.svn-base
│ ├── 14
│ │ └── 145687dbbd39240980a82be3c2191dbe27adbeb7.svn-base
│ ├── 31
│ │ └── 31fa5b53d2ee99cc83a70cd7b6e40a938584192a.svn-base
│ ├── 35
│ │ └── 35ca28cdbb212095f67b486113bf6d380aa3e5e6.svn-base
│ ├── 40
│ │ ├── 40651567fee77e7d010d5e9274037c6155dc15ba.svn-base
│ │ └── 40efa7c3eb902c3370ec0c384723cd7f7392e176.svn-base
│ ├── 52
│ │ ├── 5214979ac5a07cf1c6774bb6b0de4755cb3733a5.svn-base
│ │ └── 524d0ea881221e8df4550748671ed3c0e86a2b5c.svn-base
│ ├── 59
│ │ └── 59d14805d44a773d5c83223fc994c19974310334.svn-base
│ ├── 60
│ │ └── 601c69c461d5ac9e2c3c78c8037047f58074e989.svn-base
│ ├── 61
│ │ └── 6192708a240d5eca879f27a77c98dc69558c7a88.svn-base
│ ├── 79
│ │ └── 79a608fcc4e5b345af7404964f700c3c559cb7ed.svn-base
│ ├── 80
│ │ └── 802829df81fefe4213bd3aef78400c976d8f98d8.svn-base
│ ├── 88
│ │ └── 8882b2e8af4a8ca8ba631e24679e9ff4fe3ac893.svn-base
│ ├── 90
│ │ ├── 907489dd1e06e94a231338b228730829caf715d7.svn-base
│ │ └── 90e7191fda5d313818b7365d2a2cee202be1e375.svn-base
│ ├── 01
│ │ └── 01870ac9ec0d23c69b485512ea7ef91543a8d988.svn-base
│ ├── 03
│ │ ├── 0350ac17255f6d23f99b4a9f003004919e310c20.svn-base
│ │ └── 03a2791271bc9370674f6f6e88e6cf9d9fe1fc46.svn-base
│ ├── 07
│ │ └── 071be9703a5d7e9fb80499fd20c4587c946e7bfe.svn-base
│ ├── 1a
│ │ └── 1a15283d739bd2b4a5967cefb053477031c1ab25.svn-base
│ ├── 2b
│ │ └── 2b81c6cb47e79124eafe37a391b87f7c50d65807.svn-base
│ ├── 2f
│ │ └── 2f090cf62c8e05dbc46dea5ee27251523ed9b134.svn-base
│ ├── 3d
│ │ └── 3d2375fdfd060ea4d532f58405c2e1a4d7b3a394.svn-base
│ ├── 5b
│ │ └── 5ba206f23d051612e7d1eac7f5d2d07fa87a34c9.svn-base
│ ├── 6a
│ │ └── 6a9629cc3184c096bdc0cc75412cc6cfe56c9070.svn-base
│ ├── 6d
│ │ └── 6dcf794d90e5ef456a8702cb3346ec7565ee8af2.svn-base
│ ├── 7b
│ │ └── 7b213d614d18458daca4a566cc3be87b2a0c1ca2.svn-base
│ ├── 7d
│ │ └── 7d7ea6c476197a745d852601e143a5a55ad4801b.svn-base
│ ├── 8e
│ │ └── 8e14f08020bb604422ba024cf75975227041f1a0.svn-base
│ ├── 9a
│ │ ├── 9a30f13cc711f93a0dcf09f07022ccec0dabd1bb.svn-base
│ │ └── 9a963983860f096eba01fd6ac4cd273a3bfb382f.svn-base
│ ├── a6
│ │ └── a647d65fc56d06649218e84aa555fa74f6711c99.svn-base
│ ├── c1
│ │ └── c15d92a2cecc152a8e735428e425e20099c49d0f.svn-base
│ ├── c8
│ │ └── c83b4030392bfa8aaf801abb09138cd484158fd5.svn-base
│ ├── d2
│ │ └── d21ae8b67971f49eb126cc1b05d2e419d10d6431.svn-base
│ ├── d4
│ │ └── d4edb2d21e5c29ce5c645b1757077951b6a3b2dd.svn-base
│ ├── d5
│ │ └── d5ecdc4208ac1c1797d04744e2832895c7f77d48.svn-base
│ ├── d8
│ │ └── d8eb3b98218af6f8243bfc1bd78ff3d243f6e714.svn-base
│ ├── da
│ │ └── da39a3ee5e6b4b0d3255bfef95601890afd80709.svn-base
│ ├── e1
│ │ └── e190840dbaece0a76680d4e19f92a0c191045a05.svn-base
│ ├── e8
│ │ └── e8a120dfe78d41632f9431bfb30b2fa11ced2527.svn-base
│ ├── eb
│ │ └── eb7bd206d71aa62e42186bd1239639d17795f969.svn-base
│ ├── ee
│ │ └── eeee6286abac22bb2941b77bb63bbf0f8eb53a98.svn-base
│ ├── f3
│ │ └── f3837a7219ace8679117e664c433110530a6ed6a.svn-base
│ └── f9
│ │ └── f9048b6a960d338d940b094d183a825bfa34454f.svn-base
├── wc.db
└── wc.db-journal
├── .travis.yml
├── .umirc.ts
├── README.md
├── mock
└── .gitkeep
├── package.json
├── src
├── app.tsx
├── assets
│ └── yay.jpg
├── components
│ ├── DragWarpper
│ │ ├── index.less
│ │ └── index.tsx
│ ├── Widge
│ │ ├── index.less
│ │ └── index.tsx
│ └── formilyExtra
│ │ ├── DndInput.tsx
│ │ └── Options
│ │ └── index.tsx
├── contants.ts
├── global.less
├── index.stories.tsx
├── layouts
│ ├── __tests__
│ │ └── index.test.tsx
│ ├── index.css
│ └── index.tsx
├── pages
│ ├── __tests__
│ │ └── index.test.tsx
│ ├── dictionary.ts
│ ├── index.css
│ ├── index.tsx
│ └── layouts
│ │ ├── Board
│ │ ├── index.less
│ │ └── index.tsx
│ │ ├── FieldConfig
│ │ └── index.tsx
│ │ ├── Layout.less
│ │ ├── Layout.tsx
│ │ └── WidgeList
│ │ └── index.tsx
├── schemajson.ts
├── service
│ ├── data.d.ts
│ ├── form.ts
│ └── formData.ts
├── store
│ ├── Maker.ts
│ └── data.d.ts
├── utils
│ ├── data.d.ts
│ ├── request.ts
│ └── utils.ts
└── widge.ts
├── tsconfig.json
└── typings.d.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [Makefile]
16 | indent_style = tab
17 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | BROWSER=none
2 | ESLINT=1
3 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "eslint-config-umi"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /npm-debug.log*
6 | /yarn-error.log
7 | /yarn.lock
8 | /package-lock.json
9 |
10 | # production
11 | /dist
12 |
13 | # misc
14 | .DS_Store
15 |
16 | # umi
17 | .umi
18 | .umi-production
19 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | **/*.md
2 | **/*.svg
3 | **/*.ejs
4 | **/*.html
5 | package.json
6 | .umi
7 | .umi-production
8 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all",
4 | "printWidth": 100,
5 | "overrides": [
6 | {
7 | "files": ".prettierrc",
8 | "options": { "parser": "json" }
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.storybook/config.js:
--------------------------------------------------------------------------------
1 | import { configure } from '@storybook/react';
2 | import 'antd/dist/antd.css';
3 |
4 | function loadStories() {
5 | const req = require.context('../src', true, /\.stories\.tsx$/);
6 | req.keys().forEach(filename => req(filename));
7 | }
8 |
9 | configure(loadStories, module);
10 |
--------------------------------------------------------------------------------
/.storybook/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = ({ config }) => {
4 | config.module.rules.push({
5 | test: /\.(ts|tsx)$/,
6 | use: [
7 | {
8 | loader: require.resolve('awesome-typescript-loader'),
9 | },
10 | ],
11 | });
12 | config.module.rules.push({
13 | test: /\.less$/,
14 | use: [
15 | {
16 | loader: 'style-loader', // creates style nodes from JS strings
17 | },
18 | {
19 | loader: 'css-loader', // translates CSS into CommonJS
20 | options: {
21 | modules: true,
22 | },
23 | },
24 | {
25 | loader: 'less-loader', // compiles Less to CSS
26 | options: { javascriptEnabled: true },
27 | },
28 | ],
29 | });
30 | config.resolve.extensions.push('.ts', '.tsx');
31 |
32 | return config;
33 | };
34 |
--------------------------------------------------------------------------------
/.svn/entries:
--------------------------------------------------------------------------------
1 | 12
2 |
--------------------------------------------------------------------------------
/.svn/format:
--------------------------------------------------------------------------------
1 | 12
2 |
--------------------------------------------------------------------------------
/.svn/pristine/01/01870ac9ec0d23c69b485512ea7ef91543a8d988.svn-base:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | .container {
4 | padding: 10px 10px;
5 | overflow: auto;
6 | .board {
7 | border: 1px dashed rgba(236, 245, 255, 0.3);
8 | height: 79vh;
9 | overflow: auto;
10 | padding: 2px;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/.svn/pristine/03/0350ac17255f6d23f99b4a9f003004919e310c20.svn-base:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "start": "umi dev -p 3001",
5 | "build": "umi build",
6 | "test": "umi test",
7 | "lint": "eslint {src,mock,tests}/**/*.{ts,tsx} --fix",
8 | "precommit": "lint-staged",
9 | "storybook": "start-storybook -p 6006"
10 | },
11 | "dependencies": {
12 | "@ant-design/compatible": "^0.0.1-rc.1",
13 | "@formily/antd": "^1.0.3",
14 | "@formily/antd-components": "^1.0.3",
15 | "@storybook/react": "^5.3.13",
16 | "@types/classnames": "^2.2.9",
17 | "@types/react-beautiful-dnd": "^12.1.1",
18 | "@types/react-transition-group": "^4.2.4",
19 | "@types/uuid": "^3.4.7",
20 | "antd": "^4.0.0",
21 | "awesome-typescript-loader": "^5.2.1",
22 | "babel-plugin-import": "^1.13.0",
23 | "classnames": "^2.2.6",
24 | "css-loader": "^3.4.2",
25 | "immutability-helper": "^3.0.1",
26 | "less": "^3.11.1",
27 | "less-loader": "^5.0.0",
28 | "lodash": "^4.17.15",
29 | "mobx": "^5.15.4",
30 | "mobx-react": "^6.1.8",
31 | "mobx-react-lite": "^1.5.2",
32 | "react": "^16.8.6",
33 | "react-beautiful-dnd": "^13.0.0",
34 | "react-dnd": "^10.0.2",
35 | "react-dnd-html5-backend": "^10.0.2",
36 | "react-dom": "^16.8.6",
37 | "react-transition-group": "^4.3.0",
38 | "style-loader": "^1.1.3",
39 | "umi-request": "^1.2.19",
40 | "uuid": "^7.0.0",
41 | "webpack-combine-loaders": "^2.0.4"
42 | },
43 | "devDependencies": {
44 | "@types/jest": "^23.3.12",
45 | "@types/react": "^16.7.18",
46 | "@types/react-dom": "^16.0.11",
47 | "@types/react-test-renderer": "^16.0.3",
48 | "babel-eslint": "^9.0.0",
49 | "eslint": "^5.4.0",
50 | "eslint-config-umi": "^1.4.0",
51 | "eslint-plugin-flowtype": "^2.50.0",
52 | "eslint-plugin-import": "^2.14.0",
53 | "eslint-plugin-jsx-a11y": "^5.1.1",
54 | "eslint-plugin-react": "^7.11.1",
55 | "husky": "^0.14.3",
56 | "lint-staged": "^7.2.2",
57 | "react-test-renderer": "^16.7.0",
58 | "umi": "^2.9.0",
59 | "umi-plugin-react": "^1.8.0",
60 | "umi-types": "^0.3.0"
61 | },
62 | "lint-staged": {
63 | "*.{ts,tsx}": [
64 | "eslint --fix",
65 | "git add"
66 | ],
67 | "*.{js,jsx}": [
68 | "eslint --fix",
69 | "git add"
70 | ]
71 | },
72 | "engines": {
73 | "node": ">=8.0.0"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/.svn/pristine/03/03a2791271bc9370674f6f6e88e6cf9d9fe1fc46.svn-base:
--------------------------------------------------------------------------------
1 | declare module '*.css';
2 | declare module '*.png';
3 | declare module '*.less';
4 |
--------------------------------------------------------------------------------
/.svn/pristine/07/071be9703a5d7e9fb80499fd20c4587c946e7bfe.svn-base:
--------------------------------------------------------------------------------
1 | # form-making-react
--------------------------------------------------------------------------------
/.svn/pristine/10/1001f16043056312d6e6bb7ec5dfdf0e55cd2eee.svn-base:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | interface PaginationParams extends IPagenationParams {
4 | formId: string;
5 | }
6 |
7 | export async function getPaged(params: PaginationParams) {
8 | return request(`/form/data`, { method: 'get', params });
9 | }
10 |
--------------------------------------------------------------------------------
/.svn/pristine/14/145687dbbd39240980a82be3c2191dbe27adbeb7.svn-base:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "eslint-config-umi"
3 | }
4 |
--------------------------------------------------------------------------------
/.svn/pristine/1a/1a15283d739bd2b4a5967cefb053477031c1ab25.svn-base:
--------------------------------------------------------------------------------
1 | import { v4 as uuidV4 } from 'uuid';
2 | export const getItemStyle = (isDragging: any, draggableStyle: any) => ({
3 | // some basic styles to make the items look a bit nicer
4 | // userSelect: 'none',
5 |
6 | // change background colour if dragging
7 | // background: isDragging ? 'lightgreen' : 'red',
8 |
9 | // styles we need to apply on draggables
10 | ...draggableStyle,
11 | });
12 |
13 | export const getListStyle = (isDraggingOver: any) => ({
14 | // background: isDraggingOver ? 'lightblue' : 'grey',
15 | });
16 |
17 | export const getGUID = () => {
18 | return uuidV4().replace(/-/g, '');
19 | };
20 |
--------------------------------------------------------------------------------
/.svn/pristine/2b/2b81c6cb47e79124eafe37a391b87f7c50d65807.svn-base:
--------------------------------------------------------------------------------
1 | import { createFromIconfontCN } from '@ant-design/icons';
2 |
3 | export const ItemTypes = {
4 | INPUT: 'DndInput',
5 | TEXTAREA: 'DndTextarea',
6 | SELECT: 'DndSelect',
7 | DATEPICKER: 'DndDatePicker',
8 | INPUTNUMBER: 'DndInputNumber',
9 | CHECKBOX: 'DndCheckbox',
10 | RADIO: 'DndRadio',
11 | SWITCH: 'DndSwitch',
12 | RANGPICKER: 'DndRangePicker',
13 | };
14 |
15 | export const Accept = [
16 | ItemTypes.INPUT,
17 | ItemTypes.TEXTAREA,
18 | ItemTypes.SELECT,
19 | ItemTypes.DATEPICKER,
20 | ItemTypes.INPUTNUMBER,
21 | ItemTypes.CHECKBOX,
22 | ItemTypes.RADIO,
23 | ItemTypes.SWITCH,
24 | ItemTypes.RANGPICKER,
25 | ];
26 |
27 | export const MyIcon = createFromIconfontCN({
28 | scriptUrl: '//at.alicdn.com/t/font_1660311_lyo1k8r276.js',
29 | });
30 |
--------------------------------------------------------------------------------
/.svn/pristine/2f/2f090cf62c8e05dbc46dea5ee27251523ed9b134.svn-base:
--------------------------------------------------------------------------------
1 | export const BASE = {
2 | type: 'object',
3 | properties: {
4 | title: {
5 | title: '标题',
6 | type: 'string',
7 | },
8 | placeholder: {
9 | title: '占位内容',
10 | type: 'string',
11 | },
12 | require: {
13 | title: '必填',
14 | type: 'Switch',
15 | },
16 | disabled: {
17 | title: '禁用',
18 | type: 'Switch',
19 | },
20 | },
21 | };
22 |
23 | export const DndInput = {
24 | type: 'object',
25 | properties: {
26 | title: {
27 | title: '标题',
28 | type: 'string',
29 | },
30 | placeholder: {
31 | title: '占位内容',
32 | type: 'string',
33 | },
34 | required: {
35 | title: '必填',
36 | type: 'Switch',
37 | },
38 | disabled: {
39 | title: '禁用',
40 | type: 'Switch',
41 | },
42 | },
43 | };
44 |
45 | export const DndDatePicker = {
46 | type: 'object',
47 | properties: {
48 | title: {
49 | title: '标题',
50 | type: 'string',
51 | },
52 | placeholder: {
53 | title: '占位内容',
54 | type: 'string',
55 | },
56 | required: {
57 | title: '必填',
58 | type: 'Switch',
59 | },
60 | disabled: {
61 | title: '禁用',
62 | type: 'Switch',
63 | },
64 | },
65 | };
66 |
67 | export const DndInputNumber = {
68 | type: 'object',
69 | properties: {
70 | title: {
71 | title: '标题',
72 | type: 'string',
73 | },
74 | placeholder: {
75 | title: '占位内容',
76 | type: 'string',
77 | },
78 | required: {
79 | title: '必填',
80 | type: 'Switch',
81 | },
82 | disabled: {
83 | title: '禁用',
84 | type: 'Switch',
85 | },
86 | },
87 | };
88 |
89 | export const DndTextarea = {
90 | type: 'object',
91 | properties: {
92 | title: {
93 | title: '标题',
94 | type: 'string',
95 | },
96 | placeholder: {
97 | title: '占位内容',
98 | type: 'string',
99 | },
100 | required: {
101 | title: '必填',
102 | type: 'Switch',
103 | },
104 | disabled: {
105 | title: '禁用',
106 | type: 'Switch',
107 | },
108 | },
109 | };
110 |
111 | export const DndSelect = {
112 | type: 'object',
113 | properties: {
114 | title: {
115 | title: '标题',
116 | type: 'string',
117 | },
118 | placeholder: {
119 | title: '占位内容',
120 | type: 'string',
121 | },
122 | required: {
123 | title: '必填',
124 | type: 'Switch',
125 | },
126 | disabled: {
127 | title: '禁用',
128 | type: 'Switch',
129 | },
130 | enum: {
131 | title: '简单数据',
132 | type: 'Options',
133 | },
134 | },
135 | };
136 |
137 | export const DndCheckbox = {
138 | type: 'object',
139 | properties: {
140 | title: {
141 | title: '标题',
142 | type: 'string',
143 | },
144 | placeholder: {
145 | title: '占位内容',
146 | type: 'string',
147 | },
148 | required: {
149 | title: '必填',
150 | type: 'Switch',
151 | },
152 | disabled: {
153 | title: '禁用',
154 | type: 'Switch',
155 | },
156 | enum: {
157 | title: '简单数据',
158 | type: 'Options',
159 | },
160 | },
161 | };
162 |
163 | export const DndRadio = {
164 | type: 'object',
165 | properties: {
166 | title: {
167 | title: '标题',
168 | type: 'string',
169 | },
170 | placeholder: {
171 | title: '占位内容',
172 | type: 'string',
173 | },
174 | required: {
175 | title: '必填',
176 | type: 'Switch',
177 | },
178 | disabled: {
179 | title: '禁用',
180 | type: 'Switch',
181 | },
182 | enum: {
183 | title: '简单数据',
184 | type: 'Options',
185 | },
186 | },
187 | };
188 |
189 | export const DndSwitch = {
190 | type: 'object',
191 | properties: {
192 | title: {
193 | title: '标题',
194 | type: 'string',
195 | },
196 | required: {
197 | title: '必填',
198 | type: 'Switch',
199 | },
200 | disabled: {
201 | title: '禁用',
202 | type: 'Switch',
203 | },
204 | },
205 | };
206 |
207 | export const DndRangePicker = {
208 | type: 'object',
209 | properties: {
210 | title: {
211 | title: '标题',
212 | type: 'string',
213 | },
214 | required: {
215 | title: '必填',
216 | type: 'Switch',
217 | },
218 | disabled: {
219 | title: '禁用',
220 | type: 'Switch',
221 | },
222 | },
223 | };
224 |
--------------------------------------------------------------------------------
/.svn/pristine/31/31fa5b53d2ee99cc83a70cd7b6e40a938584192a.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Input } from 'antd';
3 | import DragWarpper from '../DragWarpper';
4 |
5 | export const DndInput = (props: any) => {
6 | console.log(props);
7 | const { placeholder, required } = props;
8 | return ;
9 | };
10 |
--------------------------------------------------------------------------------
/.svn/pristine/35/35ca28cdbb212095f67b486113bf6d380aa3e5e6.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Layout from './layouts/layout';
3 | import Board from './layouts/Board';
4 | import WidgeList from './layouts/WidgeList';
5 | import { makerContext, Maker } from '@/store/Maker';
6 | import 'antd/dist/antd.css';
7 | import ConfigBlock from './layouts/FieldConfig';
8 | import { ConfigProvider } from 'antd';
9 | import zhCN from 'antd/es/locale/zh_CN';
10 | import { getGUID } from '@/utils/utils';
11 |
12 | export default function() {
13 | const store = React.useRef(new Maker()).current;
14 |
15 | return (
16 |
17 |
18 | }
20 | left={}
21 | center={}
22 | >
23 |
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/.svn/pristine/3d/3d2375fdfd060ea4d532f58405c2e1a4d7b3a394.svn-base:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "lib": ["dom", "dom.iterable", "esnext"],
7 | "skipLibCheck": true,
8 | "importHelpers": true,
9 | "jsx": "react",
10 | "esModuleInterop": true,
11 | "sourceMap": true,
12 | "baseUrl": ".",
13 | "strict": true,
14 | "experimentalDecorators": true,
15 | "emitDecoratorMetadata": true,
16 | "paths": {
17 | "@/*": ["src/*"],
18 | "@tmp/*": ["src/pages/.umi/*"]
19 | },
20 | "allowSyntheticDefaultImports": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.svn/pristine/40/40651567fee77e7d010d5e9274037c6155dc15ba.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Button } from '@storybook/react/demo';
3 |
4 | export default { title: 'Button' };
5 |
6 | export const withText = () => ;
7 |
8 | export const withEmoji = () => (
9 |
14 | );
15 |
--------------------------------------------------------------------------------
/.svn/pristine/40/40efa7c3eb902c3370ec0c384723cd7f7392e176.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form } from '@ant-design/compatible';
3 | import '@ant-design/compatible/assets/index.css';
4 | import { Tabs, Checkbox } from 'antd';
5 | import {
6 | SchemaForm,
7 | SchemaMarkupField as Field,
8 | createAsyncFormActions,
9 | FormSlot,
10 | } from '@formily/antd';
11 | import { setup } from '@formily/antd-components';
12 | import { Switch } from '@formily/antd-components';
13 | import Options from '@/components/formilyExtra/Options';
14 | import { MakerItemProps, Maker, makerContext } from '@/store/Maker';
15 | import { toJS } from 'mobx';
16 | import { observer } from 'mobx-react-lite';
17 | import * as configSchema from '@/schemajson';
18 | import { ItemTypes } from '@/contants';
19 |
20 | setup();
21 |
22 | const { TabPane } = Tabs;
23 | const ConfigBlock = () => {
24 | const maker = React.useContext(makerContext)!;
25 |
26 | React.useEffect(() => {
27 | console.log(toJS(maker.selected));
28 | if (!!maker.selected) {
29 | actions.setFormState(state => {
30 | state.values = toJS(maker.selected?.fieldProps!);
31 | });
32 | }
33 | }, [maker.selected]);
34 |
35 | const actions = React.useRef(createAsyncFormActions()).current;
36 |
37 | const selected = maker.selected;
38 |
39 | const type = selected?.type;
40 |
41 | const getSchema = (type: string) => {
42 | if (!!type) {
43 | return (configSchema as any)[type];
44 | }
45 | return undefined;
46 | };
47 |
48 | const [value, setValue] = React.useState({});
49 |
50 | return (
51 |
52 |
53 |
54 | {
61 | maker.mutePrpos(value);
62 | }}
63 | >
64 |
65 |
66 |
67 | );
68 | };
69 |
70 | export default observer(ConfigBlock);
71 |
--------------------------------------------------------------------------------
/.svn/pristine/52/5214979ac5a07cf1c6774bb6b0de4755cb3733a5.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ConfigProvider } from 'antd';
3 |
4 | export function rootContainer(container: any) {
5 | return React.createElement(ConfigProvider, null, container);
6 | }
7 |
--------------------------------------------------------------------------------
/.svn/pristine/52/524d0ea881221e8df4550748671ed3c0e86a2b5c.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './index.less';
3 | import { Form } from '@ant-design/compatible';
4 | import '@ant-design/compatible/assets/index.css';
5 |
6 | import { observer } from 'mobx-react-lite';
7 |
8 | import { ItemTypes } from '@/contants';
9 | import { useDrag, useDrop } from 'react-dnd';
10 |
11 | const formItemLayout = {
12 | labelCol: { span: 4 },
13 | wrapperCol: { span: 12 },
14 | };
15 |
16 | export interface FBProps {
17 | onSelected: (item: any) => void;
18 | onDelete: (uuid: string) => void;
19 | data: any;
20 | selected: any | undefined;
21 | index: number;
22 | onEnd: () => void;
23 | moveItem: (dragIndex: number, hoverIndex: number) => void;
24 | onAddCopy: () => void;
25 | widge: any;
26 | }
27 |
28 | const DragWarpper: React.SFC = props => {
29 | const {
30 | selected,
31 | onSelected,
32 | data,
33 | onDelete,
34 | widge,
35 | index,
36 | onEnd,
37 | moveItem,
38 | onAddCopy,
39 | children,
40 | } = props;
41 |
42 | const isCurrent = selected && selected.fieldProps && selected.fieldProps.name === data.name;
43 |
44 | const ref = React.useRef(null);
45 |
46 | const [{ isDragging }, drag] = useDrag({
47 | item: { type: ItemTypes.INPUT, index: index },
48 | end: () => onEnd(),
49 | collect: monitor => ({
50 | isDragging: monitor.isDragging(),
51 | }),
52 | });
53 |
54 | const [{ isHover }, drop] = useDrop({
55 | accept: ItemTypes.INPUT,
56 | hover: (item: any, monitor) => {
57 | if (!ref.current) {
58 | return;
59 | }
60 |
61 | const dragIndex = item.index;
62 |
63 | //drop new here
64 | if (dragIndex === undefined) {
65 | // maker.appendItem({ uuid: '', currentIndex: maker.MakerItems.length });
66 | return;
67 | }
68 |
69 | const hoverIndex = index!;
70 |
71 | if (hoverIndex === undefined) return;
72 | if (dragIndex === hoverIndex) {
73 | return;
74 | }
75 | // Determine rectangle on screen
76 | const hoverBoundingRect = (ref!.current as any).getBoundingClientRect();
77 | // Get vertical middle
78 | const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
79 | // Determine mouse position
80 | const clientOffset = monitor.getClientOffset()!;
81 | // Get pixels to the top
82 | const hoverClientY = clientOffset.y - hoverBoundingRect.top;
83 | // Only perform the move when the mouse has crossed half of the items height
84 | // When dragging downwards, only move when the cursor is below 50%
85 | // When dragging upwards, only move when the cursor is above 50%
86 | // Dragging downwards
87 | if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
88 | return;
89 | }
90 | // Dragging upwards
91 | if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
92 | return;
93 | }
94 | // Time to actually perform the action
95 | moveItem(dragIndex, hoverIndex);
96 | // Note: we're mutating the monitor item here!
97 | // Generally it's better to avoid mutations,
98 | // but it's good here for the sake of performance
99 | // to avoid expensive index searches.
100 | item.index = hoverIndex;
101 | },
102 | drop: (item: any) => {
103 | const dragIndex = item.index;
104 | // if (dragIndex === undefined) {
105 | // maker.appendItem(item.type);
106 | // }
107 | },
108 | collect: montitor => ({
109 | isHover: !!montitor.isOver(),
110 | }),
111 | });
112 |
113 | drag(drop(ref));
114 |
115 | const renderDragIcon = () => {
116 | return (
117 |
132 | );
133 | };
134 |
135 | const renderActions = () => {
136 | return (
137 | <>
138 |
156 |
172 | >
173 | );
174 | };
175 |
176 | const containerStyles = isCurrent ? styles['contianer-active'] : styles.container;
177 | const opacity = isDragging ? 0 : 1;
178 | return (
179 | onSelected(widge)}
183 | ref={ref}
184 | >
185 | {children}
186 | {isCurrent && (
187 | <>
188 |
{renderDragIcon()}
189 |
190 | {renderActions()}
191 |
192 | >
193 | )}
194 |
195 | );
196 | };
197 |
198 | export default observer(DragWarpper);
199 |
--------------------------------------------------------------------------------
/.svn/pristine/59/59d14805d44a773d5c83223fc994c19974310334.svn-base:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | export async function add(data: FormEntity) {
4 | return request('/form', { method: 'post', data: data });
5 | }
6 |
7 | export async function getById(formId: string) {
8 | return request(`/form/${formId}`);
9 | }
10 |
11 | export async function update(data: FormEntity) {
12 | return request('/form', { method: 'put', data });
13 | }
14 |
15 | export async function deleteById(formId: string) {
16 | return request(`/form/${formId}`, { method: 'delete' });
17 | }
18 |
19 | export async function getPaged(params: IPagenationParams) {
20 | return request(`/form`, { params });
21 | }
22 |
23 | export async function submit(data: FMFormData) {
24 | return request(`/form/data`, { method: 'post', data });
25 | }
26 |
--------------------------------------------------------------------------------
/.svn/pristine/5b/5ba206f23d051612e7d1eac7f5d2d07fa87a34c9.svn-base:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /npm-debug.log*
6 | /yarn-error.log
7 | /yarn.lock
8 | /package-lock.json
9 |
10 | # production
11 | /dist
12 |
13 | # misc
14 | .DS_Store
15 |
16 | # umi
17 | .umi
18 | .umi-production
19 |
--------------------------------------------------------------------------------
/.svn/pristine/60/601c69c461d5ac9e2c3c78c8037047f58074e989.svn-base:
--------------------------------------------------------------------------------
1 | import 'jest';
2 | import Index from '..';
3 | import React from 'react';
4 | import renderer, { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
5 |
6 |
7 | describe('Page: index', () => {
8 | it('Render correctly', () => {
9 | const wrapper: ReactTestRenderer = renderer.create();
10 | expect(wrapper.root.children.length).toBe(1);
11 | const outerLayer = wrapper.root.children[0] as ReactTestInstance;
12 | expect(outerLayer.type).toBe('div');
13 | expect(outerLayer.children.length).toBe(2);
14 |
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/.svn/pristine/61/6192708a240d5eca879f27a77c98dc69558c7a88.svn-base:
--------------------------------------------------------------------------------
1 | interface BasicProps {
2 | required?: boolean;
3 | disabled?: boolean;
4 | label?: string;
5 | placeholder?: string;
6 | readonly?: string;
7 | default?: string | any;
8 | }
9 |
10 | interface DatePickerProps extends BasicProps {
11 | picker?: string;
12 | format?: string; //日期格式 默认 yyyy-MM-dd
13 | timestamp?: boolean; //是否获取时间戳
14 | }
15 |
16 | interface SelectProps extends BasicProps {
17 | mode: string;
18 | enum: any[];
19 | }
20 |
--------------------------------------------------------------------------------
/.svn/pristine/6a/6a9629cc3184c096bdc0cc75412cc6cfe56c9070.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './index.css';
3 |
4 | const BasicLayout: React.FC = props => {
5 | return {props.children}
;
6 | };
7 |
8 | export default BasicLayout;
9 |
--------------------------------------------------------------------------------
/.svn/pristine/6d/6dcf794d90e5ef456a8702cb3346ec7565ee8af2.svn-base:
--------------------------------------------------------------------------------
1 | interface FMComponent {
2 | id?: string;
3 | name?: string;
4 | type?: string;
5 | }
6 |
7 | interface FMFieldList {
8 | componentId?: string;
9 | value?: string | number;
10 | }
11 |
12 | interface FormEntity {
13 | addUserId?: string;
14 | componentList?: FMComponent[];
15 | name?: string;
16 | style?: string;
17 | remark?: string;
18 | }
19 |
20 | interface IPagenationParams {
21 | pageNum: number;
22 | pageSize: number;
23 | }
24 |
25 | interface FMFormData {
26 | addUserId?: string;
27 | fieldList?: FMFieldList[];
28 | formId?: string;
29 | }
30 |
--------------------------------------------------------------------------------
/.svn/pristine/79/79a608fcc4e5b345af7404964f700c3c559cb7ed.svn-base:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | .left {
4 | border: 1px solid @border-color-base;
5 | width: 460px;
6 | margin-right: 5px;
7 | overflow: auto;
8 | }
9 |
10 | .center {
11 | width: 100%;
12 | border: 1px solid @border-color-base;
13 | }
14 |
15 | .right {
16 | width: 480px;
17 | border: 1px solid @border-color-base;
18 | margin-left: 5px;
19 | overflow: auto;
20 | }
21 |
22 | .header {
23 | // color: hsla(0, 0%, 100%, 0.7);
24 | // background-color: #24292e;
25 | background-image: linear-gradient(90deg, #40a9ff, #e6f7ff);
26 | height: 46px;
27 | bottom: 1px solid @border-color-base;
28 | margin-bottom: 12px;
29 | color: whitesmoke;
30 | align-items: center;
31 | line-height: 46px;
32 | }
33 |
--------------------------------------------------------------------------------
/.svn/pristine/7b/7b213d614d18458daca4a566cc3be87b2a0c1ca2.svn-base:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | .icon-drag {
4 | font-size: 14px;
5 | &::before {
6 | content: '\E842';
7 | }
8 | }
9 |
10 | .container {
11 | width: 100%;
12 | margin-bottom: 2px;
13 | border: 1px dashed rgba(236, 245, 255, 0.3);
14 | position: relative;
15 | }
16 |
17 | .drag-view {
18 | position: absolute;
19 | height: 28px;
20 | width: 28px;
21 | left: 0px;
22 | top: 0px;
23 | background: @primary-color;
24 | line-height: 32px;
25 | text-align: center;
26 | }
27 |
28 | .action-view {
29 | position: absolute;
30 | right: 0;
31 | bottom: 0;
32 | background: @primary-color;
33 | height: 28px;
34 | width: 50px;
35 | line-height: 30px;
36 | cursor: pointer;
37 | }
38 |
39 | .contianer-active {
40 | width: 100%;
41 | margin-bottom: 2px;
42 | position: relative;
43 | border: 1px solid @primary-color !important;
44 | outline: 1px solid @primary-color;
45 | }
46 |
--------------------------------------------------------------------------------
/.svn/pristine/7d/7d7ea6c476197a745d852601e143a5a55ad4801b.svn-base:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/.svn/pristine/7d/7d7ea6c476197a745d852601e143a5a55ad4801b.svn-base
--------------------------------------------------------------------------------
/.svn/pristine/80/802829df81fefe4213bd3aef78400c976d8f98d8.svn-base:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | html,
4 | body,
5 | #root {
6 | height: 100%;
7 | }
8 |
9 | body {
10 | margin: 0;
11 | // text-rendering: optimizeLegibility;
12 | // -webkit-font-smoothing: antialiased;
13 | // -moz-osx-font-smoothing: grayscale;
14 | }
15 |
--------------------------------------------------------------------------------
/.svn/pristine/88/8882b2e8af4a8ca8ba631e24679e9ff4fe3ac893.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { observable, action, toJS, autorun } from 'mobx';
3 | import uuid, { v4 as uuidv4 } from 'uuid';
4 | import * as _ from 'lodash';
5 | import * as formSv from '@/service/form';
6 | import { message } from 'antd';
7 | import { getGUID } from '@/utils/utils';
8 |
9 | export interface MakerItemProps {
10 | label: string;
11 | required?: boolean;
12 | placeholder?: string;
13 | disabled?: boolean;
14 | default?: string | number; //默认值
15 | datePicker?: string; //时间选择器类型
16 | }
17 |
18 | interface Target {
19 | data?: any;
20 | index: number;
21 | }
22 |
23 | export class Maker {
24 | @observable FieldPropsList: any[] = [];
25 | @observable MakerItems: [] = [];
26 | @observable target: Target | undefined = undefined;
27 |
28 | @observable selected: any | undefined = undefined;
29 |
30 | @observable formId: string | undefined = undefined;
31 |
32 | constructor() {}
33 |
34 | @action
35 | resetFormId = (formId?: string) => {
36 | this.formId = formId;
37 | };
38 |
39 | @action
40 | submitFormData = (data: { [key: string]: string }) => {
41 | const fieldList: FMFieldList[] = [];
42 | Object.keys(data).forEach(key =>
43 | fieldList.push({ componentId: key, value: JSON.stringify(data[key]) }),
44 | );
45 | console.log(fieldList);
46 | const formData: FMFormData = {
47 | addUserId: '123',
48 | fieldList,
49 | formId: this.formId,
50 | };
51 | return formSv.submit(formData).then(this.resetFormId);
52 | };
53 |
54 | @action
55 | appendItem(item: any) {
56 | item.fieldProps.name = getGUID();
57 | this.FieldPropsList.push(item);
58 | }
59 |
60 | @action
61 | isCanAppend() {
62 | return this.target === undefined;
63 | }
64 |
65 | @action
66 | resetTarget(t: Target | undefined) {
67 | this.target = t;
68 | }
69 |
70 | @action
71 | resetMakerItems(makerItems: any[]) {
72 | this.FieldPropsList = makerItems;
73 | }
74 |
75 | @action
76 | deleteMakerItemById = (uuid: string) => {
77 | this.FieldPropsList = this.FieldPropsList.filter(({ fieldProps }) => fieldProps.name !== uuid);
78 | };
79 |
80 | @action
81 | resetSelected = (item: any) => {
82 | this.selected = item;
83 | };
84 |
85 | @action
86 | isSelected = (item: any) => {
87 | return this.selected?.name === item.name;
88 | };
89 |
90 | @action
91 | mutePrpos = (props: MakerItemProps) => {
92 | if (!!this.selected)
93 | this.FieldPropsList = this.FieldPropsList.map(x => {
94 | if (x.fieldProps.name === this.selected?.fieldProps.name) {
95 | return { ...x, fieldProps: props };
96 | }
97 | return x;
98 | }) as any;
99 | };
100 |
101 | @action
102 | addCopy = () => {
103 | let clone = _.cloneDeep(this.selected);
104 | clone.fieldProps.name = uuidv4();
105 | this.FieldPropsList.push(clone!);
106 | };
107 |
108 | @action
109 | clear = () => {
110 | this.FieldPropsList = [];
111 | };
112 |
113 | @action
114 | getSchema = () => {
115 | if (!!this.FieldPropsList && this.FieldPropsList.length === 0) {
116 | return undefined;
117 | }
118 |
119 | let result = {
120 | type: 'object',
121 | properties: {} as any,
122 | };
123 |
124 | this.FieldPropsList.forEach(
125 | ({ fieldProps }) => (result.properties[fieldProps.name] = { ...fieldProps }),
126 | );
127 | return result;
128 | };
129 |
130 | @action
131 | getDndSchema = () => {
132 | if (!!this.FieldPropsList && this.FieldPropsList.length === 0) {
133 | return undefined;
134 | }
135 |
136 | let result = {
137 | type: 'object',
138 | properties: {} as any,
139 | };
140 |
141 | return result;
142 | };
143 | @action
144 | saveFormData = (name?: string) => {
145 | const componentList: FMComponent[] = this.FieldPropsList.map(({ fieldProps, type }) => ({
146 | id: fieldProps.name,
147 | name: fieldProps.title,
148 | type: type,
149 | }));
150 | const formEntity: FormEntity = {
151 | addUserId: '123',
152 | componentList,
153 | name: name || getGUID(),
154 | style: JSON.stringify(this.FieldPropsList),
155 | remark: 'remark',
156 | };
157 |
158 | return formSv.add(formEntity).then(() => message.success('成功'));
159 | };
160 | }
161 |
162 | export const makerContext = React.createContext(null);
163 |
--------------------------------------------------------------------------------
/.svn/pristine/8e/8e14f08020bb604422ba024cf75975227041f1a0.svn-base:
--------------------------------------------------------------------------------
1 | BROWSER=none
2 | ESLINT=1
3 |
--------------------------------------------------------------------------------
/.svn/pristine/90/907489dd1e06e94a231338b228730829caf715d7.svn-base:
--------------------------------------------------------------------------------
1 | import 'jest';
2 | import BasicLayout from '..';
3 | import React from 'react';
4 | import renderer, { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
5 |
6 | describe('Layout: BasicLayout', () => {
7 | it('Render correctly', () => {
8 | const wrapper: ReactTestRenderer = renderer.create();
9 | expect(wrapper.root.children.length).toBe(1);
10 | const outerLayer = wrapper.root.children[0] as ReactTestInstance;
11 | expect(outerLayer.type).toBe('div');
12 | const title = outerLayer.children[0] as ReactTestInstance;
13 | expect(title.type).toBe('h1');
14 | expect(title.children[0]).toBe('Yay! Welcome to umi!');
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/.svn/pristine/90/90e7191fda5d313818b7365d2a2cee202be1e375.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Row, Col, Divider, Button, Modal } from 'antd';
3 | import { DndContext, DndProvider } from 'react-dnd';
4 | import Backend from 'react-dnd-html5-backend';
5 | import { SaveOutlined } from '@ant-design/icons';
6 | import styles from './Layout.less';
7 | import { makerContext } from '@/store/Maker';
8 | import SchemaForm, { createAsyncFormActions, SchemaMarkupField as Field } from '@formily/antd';
9 |
10 | interface Props {
11 | left: React.ReactNode;
12 | center: React.ReactNode;
13 | right: React.ReactNode;
14 | }
15 |
16 | const Layout: React.SFC = props => {
17 | const maker = React.useContext(makerContext)!;
18 | const { left, center, right } = props;
19 | const [visible, setVisible] = React.useState(false);
20 | const actions = React.useRef(createAsyncFormActions()).current;
21 | return (
22 |
23 |
24 |
25 |
33 | 未命名表单
34 |
35 |
36 |
37 | }
39 | shape="round"
40 | type="primary"
41 | onClick={() => {
42 | maker.saveFormData();
43 | }}
44 | >
45 | 保存
46 |
47 |
48 |
49 |
50 |
51 |
52 |
{left}
53 |
{center}
54 |
{right}
55 |
56 |
57 |
58 | );
59 | };
60 |
61 | export default Layout;
62 |
--------------------------------------------------------------------------------
/.svn/pristine/9a/9a30f13cc711f93a0dcf09f07022ccec0dabd1bb.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Widge from '../../../components/Widge';
3 | import { Tabs, Button } from 'antd';
4 | import { Widges } from '@/widge';
5 | import { Draggable, DragDropContext } from 'react-beautiful-dnd';
6 |
7 | interface Data {
8 | label: string;
9 | type: string;
10 | icon: string;
11 | }
12 |
13 | const { TabPane } = Tabs;
14 |
15 | const WidgeList = () => {
16 | return (
17 |
18 |
19 |
20 | {Widges.map((x, index) => (
21 |
22 | ))}
23 |
24 |
25 |
26 | );
27 | };
28 |
29 | export default WidgeList;
30 |
--------------------------------------------------------------------------------
/.svn/pristine/9a/9a963983860f096eba01fd6ac4cd273a3bfb382f.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './index.less';
3 | import { useDrag } from 'react-dnd';
4 | import { ItemTypes } from '@/contants';
5 | import { makerContext } from '@/store/Maker';
6 | import { Form } from '@ant-design/compatible';
7 | import '@ant-design/compatible/assets/index.css';
8 | import { Button } from 'antd';
9 | import { MyIcon } from '@/contants';
10 | import { Draggable, DragDropContext } from 'react-beautiful-dnd';
11 |
12 | interface Props {
13 | type: string;
14 | label: string;
15 | icon: string;
16 | index?: number;
17 | data?: any;
18 | }
19 |
20 | const Widge: React.SFC = props => {
21 | const { label, type, icon, index, data } = props;
22 | const maker = React.useContext(makerContext)!;
23 | const [{ isDragging }, drag] = useDrag({
24 | item: { type: type, fieldProps: data.fieldProps },
25 | collect: monitor => ({
26 | isDragging: !!monitor.isDragging(),
27 | }),
28 | });
29 |
30 | return (
31 |
43 | );
44 | };
45 |
46 | export default Widge;
47 |
--------------------------------------------------------------------------------
/.svn/pristine/a6/a647d65fc56d06649218e84aa555fa74f6711c99.svn-base:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = ({ config }) => {
4 | config.module.rules.push({
5 | test: /\.(ts|tsx)$/,
6 | use: [
7 | {
8 | loader: require.resolve('awesome-typescript-loader'),
9 | },
10 | ],
11 | });
12 | config.module.rules.push({
13 | test: /\.less$/,
14 | use: [
15 | {
16 | loader: 'style-loader', // creates style nodes from JS strings
17 | },
18 | {
19 | loader: 'css-loader', // translates CSS into CommonJS
20 | options: {
21 | modules: true,
22 | },
23 | },
24 | {
25 | loader: 'less-loader', // compiles Less to CSS
26 | options: { javascriptEnabled: true },
27 | },
28 | ],
29 | });
30 | config.resolve.extensions.push('.ts', '.tsx');
31 |
32 | return config;
33 | };
34 |
--------------------------------------------------------------------------------
/.svn/pristine/c1/c15d92a2cecc152a8e735428e425e20099c49d0f.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Input, Button } from 'antd';
3 |
4 | const Options = (props: any) => {
5 | const { value, onChange } = props;
6 |
7 | React.useEffect(() => {
8 | if (value) setDataSource(value);
9 | }, [value]);
10 |
11 | const [dataSource, setDataSource] = React.useState(value || []);
12 |
13 | const hanleAppendItem = () => {
14 | const text = 'option' + (dataSource.length + 1);
15 | setDataSource([...dataSource, { label: text, value: text }]);
16 | };
17 |
18 | const handleOptionChange = (item: any, index: any) => {
19 | setDataSource(dataSource.map((i, idx) => (idx === index ? item : i)));
20 | };
21 |
22 | const handelOptionDelete = (index: any) => {
23 | setDataSource(dataSource.filter((i, idx) => idx !== index));
24 | };
25 |
26 | React.useEffect(() => {
27 | onChange(dataSource);
28 | }, [dataSource, onChange]);
29 |
30 | const renderField = ({ value, label }: any, index: any) => {
31 | return (
32 |
33 | {
37 | handleOptionChange({ label: e.target.value, value }, index);
38 | }}
39 | value={label}
40 | style={{ width: '35%' }}
41 | >
42 | handleOptionChange({ label, value: e.target.value }, index)}
46 | value={value}
47 | style={{ width: '35%', marginLeft: 5 }}
48 | >
49 |
57 |
58 | );
59 | };
60 |
61 | return (
62 |
63 | {dataSource.map((i, index) => renderField(i, index))}
64 |
65 |
68 |
69 |
70 | );
71 | };
72 |
73 | export default Options;
74 |
--------------------------------------------------------------------------------
/.svn/pristine/c8/c83b4030392bfa8aaf801abb09138cd484158fd5.svn-base:
--------------------------------------------------------------------------------
1 | **/*.md
2 | **/*.svg
3 | **/*.ejs
4 | **/*.html
5 | package.json
6 | .umi
7 | .umi-production
8 |
--------------------------------------------------------------------------------
/.svn/pristine/d2/d21ae8b67971f49eb126cc1b05d2e419d10d6431.svn-base:
--------------------------------------------------------------------------------
1 | interface IWidge {
2 | icon: string;
3 | label: string;
4 | type: string;
5 | fieldProps: any;
6 | }
7 |
--------------------------------------------------------------------------------
/.svn/pristine/d4/d4edb2d21e5c29ce5c645b1757077951b6a3b2dd.svn-base:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | .form-edit-widget-label {
4 | font-size: @font-size-base;
5 | overflow: hidden;
6 | text-overflow: ellipsis;
7 | white-space: nowrap;
8 | border: 1px solid #f4f6fc;
9 |
10 | line-height: 30px;
11 | background: hsl(192, 9%, 90%);
12 | list-style: none;
13 |
14 | height: 30px;
15 |
16 | a {
17 | color: rgba(0, 0, 0, 0.65);
18 | }
19 | &:hover {
20 | color: #409eff;
21 | a {
22 | color: #409eff;
23 | }
24 | border: 1px dashed #409eff;
25 | background: #f4f6fc;
26 | transition: border-width 0.6s linear;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.svn/pristine/d5/d5ecdc4208ac1c1797d04744e2832895c7f77d48.svn-base:
--------------------------------------------------------------------------------
1 | import { ItemTypes } from './contants';
2 | import { getGUID } from './utils/utils';
3 |
4 | export const Widges = [
5 | {
6 | label: '单行文本',
7 | type: ItemTypes.INPUT,
8 | icon: 'anticoninput',
9 | fieldProps: {
10 | 'x-component': 'string',
11 | title: '单行文本',
12 | },
13 | },
14 | {
15 | label: '数字输入框',
16 | type: ItemTypes.INPUTNUMBER,
17 | icon: 'anticonfuhao-shuzishurukuang',
18 | fieldProps: {
19 | 'x-component': 'NumberPicker',
20 | title: '数字输入框',
21 | },
22 | },
23 | {
24 | label: '多行文本',
25 | type: ItemTypes.TEXTAREA,
26 | icon: 'anticontextareabt_back',
27 | uuid: getGUID(),
28 | fieldProps: {
29 | 'x-component': 'textarea',
30 | title: '多行文本',
31 | },
32 | },
33 | {
34 | label: '下拉选择器',
35 | type: ItemTypes.SELECT,
36 | icon: 'anticondrop-down',
37 | uuid: getGUID(),
38 | fieldProps: {
39 | 'x-component': 'string',
40 | title: '下拉选择器',
41 | enum: [{ label: 'option1', value: 'option1' }],
42 | },
43 | },
44 | {
45 | label: '日期选择器',
46 | type: ItemTypes.DATEPICKER,
47 | icon: 'anticonmdatepicker',
48 | uuid: getGUID(),
49 | fieldProps: {
50 | type: 'daterange',
51 | title: '日期选择器',
52 | picker: 'date',
53 | },
54 | },
55 | {
56 | label: '日期范围选择',
57 | type: ItemTypes.RANGPICKER,
58 | icon: 'anticonmdatepicker',
59 | uuid: getGUID(),
60 | fieldProps: {
61 | type: 'RangePicker',
62 | title: '日期范围选择器',
63 | picker: 'date',
64 | },
65 | },
66 | {
67 | label: '多选框',
68 | type: ItemTypes.CHECKBOX,
69 | icon: 'anticonduoxuankuang',
70 | uuid: getGUID(),
71 | fieldProps: {
72 | 'x-component': 'CheckboxGroup',
73 | title: '多选框',
74 | enum: [
75 | { label: 'One', value: '1' },
76 | { label: 'Two', value: '2' },
77 | { label: 'Three', value: '3' },
78 | { label: 'Four', value: '4' },
79 | ],
80 | },
81 | },
82 | {
83 | label: '单选框',
84 | type: ItemTypes.RADIO,
85 | icon: 'anticondanxuankuangxuanzhong',
86 | uuid: getGUID(),
87 | fieldProps: {
88 | 'x-component': 'RadioGroup',
89 | title: '单选框',
90 | enum: [
91 | { label: 'One', value: '1' },
92 | { label: 'Two', value: '2' },
93 | { label: 'Three', value: '3' },
94 | { label: 'Four', value: '4' },
95 | ],
96 | },
97 | },
98 | {
99 | label: '开关按钮',
100 | type: ItemTypes.SWITCH,
101 | icon: 'anticonkaiguananniu',
102 | uuid: getGUID(),
103 | fieldProps: {
104 | 'x-component': 'Switch',
105 | title: '开关按钮',
106 | },
107 | },
108 | ];
109 |
--------------------------------------------------------------------------------
/.svn/pristine/d8/d8eb3b98218af6f8243bfc1bd78ff3d243f6e714.svn-base:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [Makefile]
16 | indent_style = tab
17 |
--------------------------------------------------------------------------------
/.svn/pristine/da/da39a3ee5e6b4b0d3255bfef95601890afd80709.svn-base:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/.svn/pristine/da/da39a3ee5e6b4b0d3255bfef95601890afd80709.svn-base
--------------------------------------------------------------------------------
/.svn/pristine/e1/e190840dbaece0a76680d4e19f92a0c191045a05.svn-base:
--------------------------------------------------------------------------------
1 | import { configure } from '@storybook/react';
2 | import 'antd/dist/antd.css';
3 |
4 | function loadStories() {
5 | const req = require.context('../src', true, /\.stories\.tsx$/);
6 | req.keys().forEach(filename => req(filename));
7 | }
8 |
9 | configure(loadStories, module);
10 |
--------------------------------------------------------------------------------
/.svn/pristine/e8/e8a120dfe78d41632f9431bfb30b2fa11ced2527.svn-base:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all",
4 | "printWidth": 100,
5 | "overrides": [
6 | {
7 | "files": ".prettierrc",
8 | "options": { "parser": "json" }
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.svn/pristine/ee/eeee6286abac22bb2941b77bb63bbf0f8eb53a98.svn-base:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useDrop } from 'react-dnd';
3 | import { Accept } from '@/contants';
4 | import { makerContext } from '@/store/Maker';
5 | import { observer } from 'mobx-react-lite';
6 | import update from 'immutability-helper';
7 | import * as _ from 'lodash';
8 | import styles from './index.less';
9 | import * as formSv from '@/service/form';
10 | import {
11 | DatePicker,
12 | Checkbox,
13 | Switch,
14 | NumberPicker,
15 | Radio,
16 | Input,
17 | Select,
18 | } from '@formily/antd-components';
19 | import { DeleteOutlined, EyeOutlined, SmileOutlined } from '@ant-design/icons';
20 | import { Button, Divider, Modal, Table } from 'antd';
21 | import {
22 | SchemaMarkupField as Field,
23 | FormButtonGroup,
24 | Form,
25 | FormItem,
26 | Submit,
27 | registerFormFields,
28 | connect,
29 | } from '@formily/antd';
30 | import { DndInput } from '@/components/formilyExtra/DndInput';
31 |
32 | import DragWarpper from '@/components/DragWarpper';
33 | import Options from '@/components/formilyExtra/Options';
34 | import * as fdSv from '@/service/formData';
35 | import { toJS } from 'mobx';
36 |
37 | registerFormFields({
38 | DndInput: connect()(DndInput),
39 | Options: connect()(Options),
40 | });
41 |
42 | const { RangePicker } = DatePicker;
43 |
44 | const Components = {
45 | DndInput: Input,
46 | DndTextarea: Input.TextArea,
47 | DndSelect: Select,
48 | DndInputNumber: NumberPicker,
49 | DndDatePicker: DatePicker,
50 | DndCheckbox: Checkbox.Group,
51 | DndSwitch: Switch,
52 | DndRadio: Radio.Group,
53 | DndRangePicker: RangePicker,
54 | };
55 |
56 | const FormBoard = () => {
57 | const maker = React.useContext(makerContext)!;
58 |
59 | const [{ isHover }, drop] = useDrop({
60 | accept: Accept,
61 | canDrop: () => maker.isCanAppend(),
62 | collect: montior => ({ isHover: !!montior.isOver() }),
63 | drop: (item: any) => {
64 | if (item.index === undefined) {
65 | maker.appendItem(item);
66 | }
67 | },
68 | });
69 |
70 | const moveItem = React.useCallback(
71 | (dragIndex: number, hoverIndex) => {
72 | const dragItem = maker.FieldPropsList[dragIndex];
73 | maker.resetMakerItems(
74 | update(maker.FieldPropsList, {
75 | $splice: [
76 | [dragIndex, 1],
77 | [hoverIndex, 0, dragItem],
78 | ],
79 | }),
80 | );
81 | },
82 | [maker],
83 | );
84 |
85 | const [visible, setVisible] = React.useState(false);
86 | const [flVisivle, setFlVisivle] = React.useState(false);
87 | const [formList, setFormList] = React.useState([]);
88 | const [fdlVisible, setFdlVisible] = React.useState(false);
89 | const [formDataList, setFormDataList] = React.useState([]);
90 | React.useEffect(() => {
91 | loadList();
92 | }, []);
93 |
94 | React.useEffect(() => {
95 | if (maker.formId) {
96 | loadFdlist();
97 | }
98 | }, [maker.formId]);
99 |
100 | const [column, setColumn] = React.useState([]);
101 | const loadFdlist = () => {
102 | fdSv.getPaged({ pageNum: 1, pageSize: 10, formId: maker.formId! }).then(res => {
103 | console.log(toJS(maker.FieldPropsList));
104 | setColumn(
105 | maker.FieldPropsList.map(({ fieldProps }) => ({
106 | dataIndex: fieldProps.name,
107 | title: fieldProps.title,
108 | })) as any,
109 | );
110 | const ss = res.dataList.map(({ fieldList }: { fieldList: any[] }) => {
111 | let result = {} as any;
112 | fieldList.forEach(x => (result[x.componentId] = x.value));
113 | return result;
114 | });
115 | setFormDataList(ss);
116 | console.log(ss);
117 | });
118 | };
119 |
120 | const loadList = () => {
121 | formSv.getPaged({ pageNum: 1, pageSize: 10 }).then(res => setFormList(res.dataList));
122 | };
123 | return (
124 |
125 |
126 | }
129 | onClick={() => {
130 | maker.clear();
131 | }}
132 | >
133 | 清空
134 |
135 | } onClick={() => setVisible(true)}>
136 | 预览
137 |
138 |
146 |
154 |
155 |
156 |
157 |
158 |
186 |
187 |
{
195 | setVisible(false);
196 | }}
197 | >
198 |
224 |
225 |
setFdlVisible(false)}>
226 |
227 |
228 |
setFlVisivle(false)}
232 | title="表单列表"
233 | >
234 | {
240 | return (
241 | <>
242 |
254 |
255 |
258 | >
259 | );
260 | },
261 | },
262 | ]}
263 | dataSource={formList}
264 | >
265 |
266 |
267 | );
268 | };
269 |
270 | export default observer(FormBoard);
271 |
--------------------------------------------------------------------------------
/.svn/pristine/f3/f3837a7219ace8679117e664c433110530a6ed6a.svn-base:
--------------------------------------------------------------------------------
1 | /**
2 | * request 网络请求工具
3 | * 更详细的 api 文档: https://github.com/umijs/umi-request
4 | */
5 | import { extend, RequestOptionsInit } from 'umi-request';
6 | import { notification } from 'antd';
7 | import { router } from 'umi';
8 |
9 | const codeMessage = {
10 | 200: '服务器成功返回请求的数据。',
11 | 201: '新建或修改数据成功。',
12 | // 201: '服务器错误',
13 | 202: '一个请求已经进入后台排队(异步任务)。',
14 | 204: '删除数据成功。',
15 | 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
16 | 401: '用户没有权限(令牌、用户名、密码错误)。',
17 | 403: '用户得到授权,但是访问是被禁止的。',
18 | 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
19 | 406: '请求的格式不可得。',
20 | 410: '请求的资源被永久删除,且不会再得到的。',
21 | 422: '当创建一个对象时,发生一个验证错误。',
22 | 500: '服务器发生错误,请检查服务器。',
23 | 502: '网关错误。',
24 | 503: '服务不可用,服务器暂时过载或维护。',
25 | 504: '网关超时。',
26 | };
27 |
28 | /**
29 | * 异常处理程序
30 | */
31 | const errorHandler = (error: { response: Response }): Response => {
32 | const { response } = error;
33 | if (response && response.status) {
34 | const errorText = (codeMessage as any)[response.status] || response.statusText;
35 | const { status, url } = response;
36 | notification.error({
37 | message: `请求错误 ${status}: ${url}`,
38 | description: errorText,
39 | });
40 | }
41 | return response;
42 | };
43 |
44 | // export const prefix =
45 | // process.env.NODE_ENV === 'development' ? '' : 'http://47.104.131.14/digitcons/v1';
46 |
47 | export const prefix = 'http://47.104.131.14/wisdomsite/v1';
48 | // export const prefix = 'http://39.104.81.4/wisdomsite/v1'
49 |
50 | // export const prefix = 'http://www.lanlan.live:8085/wisdomsite/v1'
51 | /**
52 | * 配置request请求时的默认参数
53 | */
54 | export const urequest = extend({
55 | prefix: prefix,
56 | errorHandler, // 默认错误处理
57 | credentials: 'include', // 默认请求是否带上cookie
58 | });
59 |
60 | export const request = (url: string, options?: RequestOptionsInit) => {
61 | return new Promise(async (resolve, reject) => {
62 | const res = await urequest(url, options);
63 | if (res === null) {
64 | reject('未知错误');
65 | return;
66 | }
67 | const error = handleStatusError(res.status, url, res.message);
68 |
69 | if (error) reject(error);
70 |
71 | const boxingRes = boxingResponse(res);
72 | resolve(boxingRes);
73 | }).catch(error => {
74 | throw error;
75 | });
76 | };
77 |
78 | const handleStatusError = (status: number, url?: string, msg?: string): string | undefined => {
79 | const errorConfig = (BACKENDSTATUSERRORCONFIG as any)[status] || undefined;
80 | if (Array.isArray(errorConfig)) {
81 | const [defaultMsg, fn] = errorConfig;
82 | if (typeof fn === 'function') {
83 | fn(msg || defaultMsg, url);
84 | }
85 | return msg;
86 | }
87 |
88 | return errorConfig;
89 | };
90 |
91 | const boxingResponse = (res: any) => {
92 | const data = res.data;
93 | if (data && data.pageTool) {
94 | const pageTool = data.pageTool;
95 | return {
96 | dataList: data.beanList || [],
97 | meta: {
98 | pageNum: pageTool.pageNum,
99 | pageSize: pageTool.pageTool,
100 | total: pageTool.totalSize,
101 | },
102 | };
103 | }
104 | return res;
105 | };
106 |
107 | const BACKENDSTATUSERRORCONFIG = {
108 | 125: [
109 | 'token error!',
110 | () => {
111 | router.push('/user/login');
112 | },
113 | ],
114 | 201: [
115 | '后台服务器异常请查阅日志!',
116 | (errorText: string, url: string) => {
117 | notification.error({
118 | message: `请求错误 ${status}: ${url}`,
119 | description: errorText,
120 | });
121 | },
122 | ],
123 | 116: [
124 | '项目进度id不能为空',
125 | (errorText: string, url: string) => {
126 | notification.error({
127 | message: `请求错误 ${status}: ${url}`,
128 | description: errorText,
129 | });
130 | },
131 | ],
132 | 121: [
133 | '',
134 | (errorText: string, url: string) => {
135 | notification.error({
136 | message: `请求错误 ${status}: ${url}`,
137 | description: errorText,
138 | });
139 | },
140 | ],
141 | 10: ['', ''],
142 | };
143 |
144 | // 中间件,对请求前、响应后做处理
145 | urequest.use(async (ctx, next) => {
146 | const { req } = ctx;
147 |
148 | req.options.headers = {
149 | auth_token: 'd7dda732508242669ba1c1506935b1e8',
150 | };
151 |
152 | await next();
153 | const { res } = ctx;
154 |
155 | // if (process.env.NODE_ENV === 'development') {
156 | // console.log(`API: ${req.url.replace(prefix, '')} \r\n返回的数据: `, res.data, ' \r\n');
157 | // console.log(`\r\n`);
158 | // }
159 | });
160 |
161 | export default request;
162 |
--------------------------------------------------------------------------------
/.svn/pristine/f9/f9048b6a960d338d940b094d183a825bfa34454f.svn-base:
--------------------------------------------------------------------------------
1 | import { IConfig } from 'umi-types';
2 |
3 | // ref: https://umijs.org/config/
4 | const config: IConfig = {
5 | treeShaking: true,
6 | routes: [
7 | {
8 | path: '/',
9 | component: '../layouts/index',
10 | routes: [{ path: '/', component: '../pages/index' }],
11 | },
12 | ],
13 | plugins: [
14 | // ref: https://umijs.org/plugin/umi-plugin-react.html
15 | [
16 | 'umi-plugin-react',
17 | {
18 | antd: true,
19 | dva: false,
20 | dynamicImport: false,
21 | title: 'form-making',
22 | dll: false,
23 | routes: {
24 | exclude: [/components\//],
25 | },
26 | },
27 | ],
28 | ],
29 | };
30 |
31 | export default config;
32 |
--------------------------------------------------------------------------------
/.svn/wc.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/.svn/wc.db
--------------------------------------------------------------------------------
/.svn/wc.db-journal:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/.svn/wc.db-journal
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - lts/*
4 | install:
5 | - yarn install
6 | sciprt:
7 | - yarn build
8 | deploy:
9 | provider: pages
10 | skip_cleanup: true
11 | local_dir: dist
12 | github_token: $GITHUB_TOKEN
13 | keep_history: true
14 | on:
15 | branch: master
16 |
--------------------------------------------------------------------------------
/.umirc.ts:
--------------------------------------------------------------------------------
1 | // ref: https://umijs.org/config/
2 | const config = {
3 | base: '/form-making/',
4 | publicPath: '/form-making/',
5 | routes: [
6 | {
7 | path: '/',
8 | component: '../layouts/index',
9 | routes: [{ path: '/', component: '../pages/index' }],
10 | },
11 | ],
12 | dva: {},
13 | antd: {},
14 | };
15 |
16 | export default config;
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # form-making
2 |
3 | 简易表单编辑器
4 |
5 | ## 开始
6 | #### 1. 安装package依赖
7 | npm install 或者 yarn
8 |
9 | #### 2. 启动项目
10 | npm start 或者 yarn start
11 |
12 |
--------------------------------------------------------------------------------
/mock/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/mock/.gitkeep
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "start": "umi dev -p 3001",
5 | "build": "umi build",
6 | "test": "umi test",
7 | "lint": "eslint {src,mock,tests}/**/*.{ts,tsx} --fix",
8 | "precommit": "lint-staged",
9 | "storybook": "start-storybook -p 6006"
10 | },
11 | "dependencies": {
12 | "@ant-design/compatible": "^0.0.1-rc.1",
13 | "@formily/antd": "^1.0.3",
14 | "@formily/antd-components": "^1.0.3",
15 | "@storybook/react": "^5.3.13",
16 | "@types/classnames": "^2.2.9",
17 | "@types/react-beautiful-dnd": "^12.1.1",
18 | "@types/react-transition-group": "^4.2.4",
19 | "@types/uuid": "^3.4.7",
20 | "antd": "^4.0.0",
21 | "awesome-typescript-loader": "^5.2.1",
22 | "babel-plugin-import": "^1.13.0",
23 | "classnames": "^2.2.6",
24 | "css-loader": "^3.4.2",
25 | "immutability-helper": "^3.0.1",
26 | "less": "^3.11.1",
27 | "less-loader": "^5.0.0",
28 | "lodash": "^4.17.15",
29 | "mobx": "^5.15.4",
30 | "mobx-react": "^6.1.8",
31 | "mobx-react-lite": "^1.5.2",
32 | "react": "^16.8.6",
33 | "react-beautiful-dnd": "^13.0.0",
34 | "react-dnd": "^10.0.2",
35 | "react-dnd-html5-backend": "^10.0.2",
36 | "react-dom": "^16.8.6",
37 | "react-transition-group": "^4.3.0",
38 | "style-loader": "^1.1.3",
39 | "styled-components": "^5.3.0",
40 | "umi-request": "^1.2.19",
41 | "uuid": "^7.0.0",
42 | "webpack-combine-loaders": "^2.0.4"
43 | },
44 | "devDependencies": {
45 | "@types/jest": "^23.3.12",
46 | "@types/react": "^16.7.18",
47 | "@types/react-dom": "^16.0.11",
48 | "@types/react-test-renderer": "^16.0.3",
49 | "@umijs/preset-react": "^1",
50 | "babel-eslint": "^9.0.0",
51 | "eslint": "^5.4.0",
52 | "eslint-config-umi": "^1.4.0",
53 | "eslint-plugin-flowtype": "^2.50.0",
54 | "eslint-plugin-import": "^2.14.0",
55 | "eslint-plugin-jsx-a11y": "^5.1.1",
56 | "eslint-plugin-react": "^7.11.1",
57 | "husky": "^0.14.3",
58 | "lint-staged": "^7.2.2",
59 | "react-test-renderer": "^16.7.0",
60 | "umi": "^3",
61 | "umi-types": "^0.3.0"
62 | },
63 | "lint-staged": {
64 | "*.{ts,tsx}": [
65 | "eslint --fix",
66 | "git add"
67 | ],
68 | "*.{js,jsx}": [
69 | "eslint --fix",
70 | "git add"
71 | ]
72 | },
73 | "engines": {
74 | "node": ">=8.0.0"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/app.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ConfigProvider } from 'antd';
3 |
4 | export function rootContainer(container: any) {
5 | return React.createElement(ConfigProvider, null, container);
6 | }
7 |
--------------------------------------------------------------------------------
/src/assets/yay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/src/assets/yay.jpg
--------------------------------------------------------------------------------
/src/components/DragWarpper/index.less:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | .icon-drag {
4 | font-size: 14px;
5 | &::before {
6 | content: '\E842';
7 | }
8 | }
9 |
10 | .container {
11 | width: 100%;
12 | margin-bottom: 2px;
13 | border: 1px dashed rgba(236, 245, 255, 0.3);
14 | position: relative;
15 | }
16 |
17 | .drag-view {
18 | position: absolute;
19 | height: 28px;
20 | width: 28px;
21 | left: 0px;
22 | top: 0px;
23 | background: @primary-color;
24 | line-height: 32px;
25 | text-align: center;
26 | }
27 |
28 | .action-view {
29 | position: absolute;
30 | right: 0;
31 | bottom: 0;
32 | background: @primary-color;
33 | height: 28px;
34 | width: 50px;
35 | line-height: 30px;
36 | cursor: pointer;
37 | }
38 |
39 | .contianer-active {
40 | width: 100%;
41 | margin-bottom: 2px;
42 | position: relative;
43 | border: 1px solid @primary-color !important;
44 | outline: 1px solid @primary-color;
45 | }
46 |
--------------------------------------------------------------------------------
/src/components/DragWarpper/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './index.less';
3 | import '@ant-design/compatible/assets/index.css';
4 | import { observer } from 'mobx-react-lite';
5 | import { ItemTypes } from '@/contants';
6 | import { useDrag, useDrop } from 'react-dnd';
7 |
8 | const formItemLayout = {
9 | labelCol: { span: 4 },
10 | wrapperCol: { span: 12 },
11 | };
12 |
13 | export interface FBProps {
14 | onSelected: (item: any) => void;
15 | onDelete: (uuid: string) => void;
16 | data: any;
17 | selected: any | undefined;
18 | index: number;
19 | onEnd: () => void;
20 | moveItem: (dragIndex: number, hoverIndex: number) => void;
21 | onAddCopy: () => void;
22 | widge: any;
23 | }
24 |
25 | const DragWarpper: React.SFC = props => {
26 | const {
27 | selected,
28 | onSelected,
29 | data,
30 | onDelete,
31 | widge,
32 | index,
33 | onEnd,
34 | moveItem,
35 | onAddCopy,
36 | children,
37 | } = props;
38 |
39 | const isCurrent = selected && selected.fieldProps && selected.fieldProps.name === data.name;
40 |
41 | const ref = React.useRef(null);
42 |
43 | const [{ isDragging }, drag] = useDrag({
44 | item: { type: ItemTypes.INPUT, index: index },
45 | end: () => onEnd(),
46 | collect: monitor => ({
47 | isDragging: monitor.isDragging(),
48 | }),
49 | });
50 |
51 | const [{ isHover }, drop] = useDrop({
52 | accept: ItemTypes.INPUT,
53 | hover: (item: any, monitor) => {
54 | if (!ref.current) {
55 | return;
56 | }
57 |
58 | const dragIndex = item.index;
59 |
60 | //drop new here
61 | if (dragIndex === undefined) {
62 | // maker.appendItem({ uuid: '', currentIndex: maker.MakerItems.length });
63 | return;
64 | }
65 |
66 | const hoverIndex = index!;
67 |
68 | if (hoverIndex === undefined) return;
69 | if (dragIndex === hoverIndex) {
70 | return;
71 | }
72 | // Determine rectangle on screen
73 | const hoverBoundingRect = (ref!.current as any).getBoundingClientRect();
74 | // Get vertical middle
75 | const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
76 | // Determine mouse position
77 | const clientOffset = monitor.getClientOffset()!;
78 | // Get pixels to the top
79 | const hoverClientY = clientOffset.y - hoverBoundingRect.top;
80 | // Only perform the move when the mouse has crossed half of the items height
81 | // When dragging downwards, only move when the cursor is below 50%
82 | // When dragging upwards, only move when the cursor is above 50%
83 | // Dragging downwards
84 | if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
85 | return;
86 | }
87 | // Dragging upwards
88 | if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
89 | return;
90 | }
91 | // Time to actually perform the action
92 | moveItem(dragIndex, hoverIndex);
93 | // Note: we're mutating the monitor item here!
94 | // Generally it's better to avoid mutations,
95 | // but it's good here for the sake of performance
96 | // to avoid expensive index searches.
97 | item.index = hoverIndex;
98 | },
99 | drop: (item: any) => {
100 | const dragIndex = item.index;
101 | // if (dragIndex === undefined) {
102 | // maker.appendItem(item.type);
103 | // }
104 | },
105 | collect: montitor => ({
106 | isHover: !!montitor.isOver(),
107 | }),
108 | });
109 |
110 | drag(drop(ref));
111 |
112 | const renderDragIcon = () => {
113 | return (
114 |
129 | );
130 | };
131 |
132 | const renderActions = () => {
133 | return (
134 | <>
135 |
153 |
169 | >
170 | );
171 | };
172 |
173 | const containerStyles = isCurrent ? styles['contianer-active'] : styles.container;
174 | const opacity = isDragging ? 0 : 1;
175 | return (
176 | onSelected(widge)}
180 | ref={ref}
181 | >
182 | {children}
183 | {isCurrent && (
184 | <>
185 |
{renderDragIcon()}
186 |
187 | {renderActions()}
188 |
189 | >
190 | )}
191 |
192 | );
193 | };
194 |
195 | export default observer(DragWarpper);
196 |
--------------------------------------------------------------------------------
/src/components/Widge/index.less:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | .form-edit-widget-label {
4 | font-size: @font-size-base;
5 | overflow: hidden;
6 | text-overflow: ellipsis;
7 | white-space: nowrap;
8 | border: 1px solid #f4f6fc;
9 |
10 | line-height: 30px;
11 | background: hsl(192, 9%, 90%);
12 | list-style: none;
13 |
14 | height: 30px;
15 |
16 | a {
17 | color: rgba(0, 0, 0, 0.65);
18 | }
19 | &:hover {
20 | color: #409eff;
21 | a {
22 | color: #409eff;
23 | }
24 | border: 1px dashed #409eff;
25 | background: #f4f6fc;
26 | transition: border-width 0.6s linear;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/components/Widge/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './index.less';
3 | import { useDrag } from 'react-dnd';
4 | import { ItemTypes } from '@/contants';
5 | import { makerContext } from '@/store/Maker';
6 | import { Form } from '@ant-design/compatible';
7 | import '@ant-design/compatible/assets/index.css';
8 | import { Button } from 'antd';
9 | import { MyIcon } from '@/contants';
10 | import { Draggable, DragDropContext } from 'react-beautiful-dnd';
11 |
12 | interface Props {
13 | type: string;
14 | label: string;
15 | icon: string;
16 | index?: number;
17 | data?: any;
18 | }
19 |
20 | const Widge: React.SFC = props => {
21 | const { label, type, icon, index, data } = props;
22 | const maker = React.useContext(makerContext)!;
23 | const [{ isDragging }, drag] = useDrag({
24 | item: { type: type, fieldProps: data.fieldProps },
25 | collect: monitor => ({
26 | isDragging: !!monitor.isDragging(),
27 | }),
28 | });
29 |
30 | return (
31 |
43 | );
44 | };
45 |
46 | export default Widge;
47 |
--------------------------------------------------------------------------------
/src/components/formilyExtra/DndInput.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Input } from 'antd';
3 | import DragWarpper from '../DragWarpper';
4 |
5 | export const DndInput = (props: any) => {
6 | console.log(props);
7 | const { placeholder, required } = props;
8 | return ;
9 | };
10 |
--------------------------------------------------------------------------------
/src/components/formilyExtra/Options/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Input, Button } from 'antd';
3 |
4 | const Options = (props: any) => {
5 | const { value, onChange } = props;
6 |
7 | React.useEffect(() => {
8 | if (value) setDataSource(value);
9 | }, [value]);
10 |
11 | const [dataSource, setDataSource] = React.useState(value || []);
12 |
13 | const hanleAppendItem = () => {
14 | const text = 'option' + (dataSource.length + 1);
15 | setDataSource([...dataSource, { label: text, value: text }]);
16 | };
17 |
18 | const handleOptionChange = (item: any, index: any) => {
19 | setDataSource(dataSource.map((i, idx) => (idx === index ? item : i)));
20 | };
21 |
22 | const handelOptionDelete = (index: any) => {
23 | setDataSource(dataSource.filter((i, idx) => idx !== index));
24 | };
25 |
26 | React.useEffect(() => {
27 | onChange(dataSource);
28 | }, [dataSource, onChange]);
29 |
30 | const renderField = ({ value, label }: any, index: any) => {
31 | return (
32 |
33 | {
37 | handleOptionChange({ label: e.target.value, value }, index);
38 | }}
39 | value={label}
40 | style={{ width: '35%' }}
41 | >
42 | handleOptionChange({ label, value: e.target.value }, index)}
46 | value={value}
47 | style={{ width: '35%', marginLeft: 5 }}
48 | >
49 |
57 |
58 | );
59 | };
60 |
61 | return (
62 |
63 | {dataSource.map((i, index) => renderField(i, index))}
64 |
65 |
68 |
69 |
70 | );
71 | };
72 |
73 | export default Options;
74 |
--------------------------------------------------------------------------------
/src/contants.ts:
--------------------------------------------------------------------------------
1 | import { createFromIconfontCN } from '@ant-design/icons';
2 |
3 | export const ItemTypes = {
4 | INPUT: 'DndInput',
5 | TEXTAREA: 'DndTextarea',
6 | SELECT: 'DndSelect',
7 | DATEPICKER: 'DndDatePicker',
8 | INPUTNUMBER: 'DndInputNumber',
9 | CHECKBOX: 'DndCheckbox',
10 | RADIO: 'DndRadio',
11 | SWITCH: 'DndSwitch',
12 | RANGPICKER: 'DndRangePicker',
13 | };
14 |
15 | export const Accept = [
16 | ItemTypes.INPUT,
17 | ItemTypes.TEXTAREA,
18 | ItemTypes.SELECT,
19 | ItemTypes.DATEPICKER,
20 | ItemTypes.INPUTNUMBER,
21 | ItemTypes.CHECKBOX,
22 | ItemTypes.RADIO,
23 | ItemTypes.SWITCH,
24 | ItemTypes.RANGPICKER,
25 | ];
26 |
27 | export const MyIcon = createFromIconfontCN({
28 | scriptUrl: '//at.alicdn.com/t/font_1660311_lyo1k8r276.js',
29 | });
30 |
--------------------------------------------------------------------------------
/src/global.less:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | html,
4 | body,
5 | #root {
6 | height: 100%;
7 | }
8 |
9 | body {
10 | margin: 0;
11 | // text-rendering: optimizeLegibility;
12 | // -webkit-font-smoothing: antialiased;
13 | // -moz-osx-font-smoothing: grayscale;
14 | }
15 |
--------------------------------------------------------------------------------
/src/index.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Button } from '@storybook/react/demo';
3 |
4 | export default { title: 'Button' };
5 |
6 | export const withText = () => ;
7 |
8 | export const withEmoji = () => (
9 |
14 | );
15 |
--------------------------------------------------------------------------------
/src/layouts/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | import 'jest';
2 | import BasicLayout from '..';
3 | import React from 'react';
4 | import renderer, { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
5 |
6 | describe('Layout: BasicLayout', () => {
7 | it('Render correctly', () => {
8 | const wrapper: ReactTestRenderer = renderer.create();
9 | expect(wrapper.root.children.length).toBe(1);
10 | const outerLayer = wrapper.root.children[0] as ReactTestInstance;
11 | expect(outerLayer.type).toBe('div');
12 | const title = outerLayer.children[0] as ReactTestInstance;
13 | expect(title.type).toBe('h1');
14 | expect(title.children[0]).toBe('Yay! Welcome to umi!');
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/layouts/index.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/src/layouts/index.css
--------------------------------------------------------------------------------
/src/layouts/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const BasicLayout: React.FC = props => {
4 | return {props.children}
;
5 | };
6 |
7 | export default BasicLayout;
8 |
--------------------------------------------------------------------------------
/src/pages/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | import 'jest';
2 | import Index from '..';
3 | import React from 'react';
4 | import renderer, { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
5 |
6 |
7 | describe('Page: index', () => {
8 | it('Render correctly', () => {
9 | const wrapper: ReactTestRenderer = renderer.create();
10 | expect(wrapper.root.children.length).toBe(1);
11 | const outerLayer = wrapper.root.children[0] as ReactTestInstance;
12 | expect(outerLayer.type).toBe('div');
13 | expect(outerLayer.children.length).toBe(2);
14 |
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/pages/dictionary.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/src/pages/dictionary.ts
--------------------------------------------------------------------------------
/src/pages/index.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yzz421/form-making/c2343bada0f12abfa11bc9a2981a6b67717b93ad/src/pages/index.css
--------------------------------------------------------------------------------
/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Layout from './layouts/Layout';
3 | import Board from './layouts/Board';
4 | import WidgeList from './layouts/WidgeList';
5 | import { makerContext, Maker } from '@/store/Maker';
6 | import 'antd/dist/antd.css';
7 | import ConfigBlock from './layouts/FieldConfig';
8 | import { ConfigProvider } from 'antd';
9 | import zhCN from 'antd/es/locale/zh_CN';
10 |
11 | export default function() {
12 | const store = React.useRef(new Maker()).current;
13 |
14 | return (
15 |
16 |
17 | }
19 | left={}
20 | center={}
21 | >
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/src/pages/layouts/Board/index.less:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | .container {
4 | padding: 10px 10px;
5 | overflow: auto;
6 | .board {
7 | border: 1px dashed rgba(236, 245, 255, 0.3);
8 | height: 79vh;
9 | overflow: auto;
10 | padding: 2px;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/pages/layouts/Board/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useDrop } from 'react-dnd';
3 | import { Accept } from '@/contants';
4 | import { makerContext } from '@/store/Maker';
5 | import { observer } from 'mobx-react-lite';
6 | import update from 'immutability-helper';
7 | import * as _ from 'lodash';
8 | import styles from './index.less';
9 | import * as formSv from '@/service/form';
10 | import {
11 | DatePicker,
12 | Checkbox,
13 | Switch,
14 | NumberPicker,
15 | Radio,
16 | Input,
17 | Select,
18 | } from '@formily/antd-components';
19 | import { DeleteOutlined, EyeOutlined, SmileOutlined } from '@ant-design/icons';
20 | import { Button, Divider, Modal, Table } from 'antd';
21 | import {
22 | SchemaMarkupField as Field,
23 | FormButtonGroup,
24 | Form,
25 | FormItem,
26 | Submit,
27 | registerFormFields,
28 | connect,
29 | } from '@formily/antd';
30 | import { DndInput } from '@/components/formilyExtra/DndInput';
31 |
32 | import DragWarpper from '@/components/DragWarpper';
33 | import Options from '@/components/formilyExtra/Options';
34 | import * as fdSv from '@/service/formData';
35 | import { toJS } from 'mobx';
36 |
37 | registerFormFields({
38 | DndInput: connect()(DndInput),
39 | Options: connect()(Options),
40 | });
41 |
42 | const { RangePicker } = DatePicker;
43 |
44 | const Components = {
45 | DndInput: Input,
46 | DndTextarea: Input.TextArea,
47 | DndSelect: Select,
48 | DndInputNumber: NumberPicker,
49 | DndDatePicker: DatePicker,
50 | DndCheckbox: Checkbox.Group,
51 | DndSwitch: Switch,
52 | DndRadio: Radio.Group,
53 | DndRangePicker: RangePicker,
54 | };
55 |
56 | const FormBoard = () => {
57 | const maker = React.useContext(makerContext)!;
58 |
59 | const [{ isHover }, drop] = useDrop({
60 | accept: Accept,
61 | canDrop: () => maker.isCanAppend(),
62 | collect: montior => ({ isHover: !!montior.isOver() }),
63 | drop: (item: any) => {
64 | if (item.index === undefined) {
65 | maker.appendItem(item);
66 | }
67 | },
68 | });
69 |
70 | const moveItem = React.useCallback(
71 | (dragIndex: number, hoverIndex) => {
72 | const dragItem = maker.FieldPropsList[dragIndex];
73 | maker.resetMakerItems(
74 | update(maker.FieldPropsList, {
75 | $splice: [
76 | [dragIndex, 1],
77 | [hoverIndex, 0, dragItem],
78 | ],
79 | }),
80 | );
81 | },
82 | [maker],
83 | );
84 |
85 | const [visible, setVisible] = React.useState(false);
86 | const [flVisivle, setFlVisivle] = React.useState(false);
87 | const [formList, setFormList] = React.useState([]);
88 | const [fdlVisible, setFdlVisible] = React.useState(false);
89 | const [formDataList, setFormDataList] = React.useState([]);
90 | React.useEffect(() => {
91 | loadList();
92 | }, []);
93 |
94 | React.useEffect(() => {
95 | if (maker.formId) {
96 | loadFdlist();
97 | }
98 | }, [maker.formId]);
99 |
100 | const [column, setColumn] = React.useState([]);
101 | const loadFdlist = () => {
102 | fdSv.getPaged({ pageNum: 1, pageSize: 10, formId: maker.formId! }).then(res => {
103 | console.log(toJS(maker.FieldPropsList));
104 | setColumn(
105 | maker.FieldPropsList.map(({ fieldProps }) => ({
106 | dataIndex: fieldProps.name,
107 | title: fieldProps.title,
108 | })) as any,
109 | );
110 | const ss = res.dataList.map(({ fieldList }: { fieldList: any[] }) => {
111 | let result = {} as any;
112 | fieldList.forEach(x => (result[x.componentId] = x.value));
113 | return result;
114 | });
115 | setFormDataList(ss);
116 | console.log(ss);
117 | });
118 | };
119 |
120 | const loadList = () => {
121 | formSv.getPaged({ pageNum: 1, pageSize: 10 }).then(res => setFormList(res.dataList));
122 | };
123 | return (
124 |
125 |
126 | }
129 | onClick={() => {
130 | maker.clear();
131 | }}
132 | >
133 | 清空
134 |
135 | } onClick={() => setVisible(true)}>
136 | 预览
137 |
138 |
146 |
154 |
155 |
156 |
157 |
158 |
186 |
187 |
{
195 | setVisible(false);
196 | }}
197 | >
198 |
224 |
225 |
setFdlVisible(false)}>
226 |
227 |
228 |
setFlVisivle(false)}
232 | title="表单列表"
233 | >
234 | {
240 | return (
241 | <>
242 |
254 |
255 |
258 | >
259 | );
260 | },
261 | },
262 | ]}
263 | dataSource={formList}
264 | >
265 |
266 |
267 | );
268 | };
269 |
270 | export default observer(FormBoard);
271 |
--------------------------------------------------------------------------------
/src/pages/layouts/FieldConfig/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form } from '@ant-design/compatible';
3 | import '@ant-design/compatible/assets/index.css';
4 | import { Tabs, Checkbox } from 'antd';
5 | import {
6 | SchemaForm,
7 | SchemaMarkupField as Field,
8 | createAsyncFormActions,
9 | FormSlot,
10 | } from '@formily/antd';
11 | import { setup } from '@formily/antd-components';
12 | import { Switch } from '@formily/antd-components';
13 | import Options from '@/components/formilyExtra/Options';
14 | import { MakerItemProps, Maker, makerContext } from '@/store/Maker';
15 | import { toJS } from 'mobx';
16 | import { observer } from 'mobx-react-lite';
17 | import * as configSchema from '@/schemajson';
18 | import { ItemTypes } from '@/contants';
19 |
20 | setup();
21 |
22 | const { TabPane } = Tabs;
23 | const ConfigBlock = () => {
24 | const maker = React.useContext(makerContext)!;
25 |
26 | React.useEffect(() => {
27 | console.log(toJS(maker.selected));
28 | if (!!maker.selected) {
29 | actions.setFormState(state => {
30 | state.values = toJS(maker.selected?.fieldProps!);
31 | });
32 | }
33 | }, [maker.selected]);
34 |
35 | const actions = React.useRef(createAsyncFormActions()).current;
36 |
37 | const selected = maker.selected;
38 |
39 | const type = selected?.type;
40 |
41 | const getSchema = (type: string) => {
42 | if (!!type) {
43 | return (configSchema as any)[type];
44 | }
45 | return undefined;
46 | };
47 |
48 | const [value, setValue] = React.useState({});
49 |
50 | return (
51 |
52 |
53 |
54 | {
61 | maker.mutePrpos(value);
62 | }}
63 | >
64 |
65 |
66 |
67 | );
68 | };
69 |
70 | export default observer(ConfigBlock);
71 |
--------------------------------------------------------------------------------
/src/pages/layouts/Layout.less:
--------------------------------------------------------------------------------
1 | @import '~antd/es/style/themes/default.less';
2 |
3 | .left {
4 | border: 1px solid @border-color-base;
5 | width: 460px;
6 | margin-right: 5px;
7 | overflow: auto;
8 | }
9 |
10 | .center {
11 | width: 100%;
12 | border: 1px solid @border-color-base;
13 | }
14 |
15 | .right {
16 | width: 480px;
17 | border: 1px solid @border-color-base;
18 | margin-left: 5px;
19 | overflow: auto;
20 | }
21 |
22 | .header {
23 | // color: hsla(0, 0%, 100%, 0.7);
24 | // background-color: #24292e;
25 | background-image: linear-gradient(90deg, #40a9ff, #e6f7ff);
26 | height: 46px;
27 | bottom: 1px solid @border-color-base;
28 | margin-bottom: 12px;
29 | color: whitesmoke;
30 | align-items: center;
31 | line-height: 46px;
32 | }
33 |
--------------------------------------------------------------------------------
/src/pages/layouts/Layout.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Row, Col, Divider, Button, Modal } from 'antd';
3 | import { DndContext, DndProvider } from 'react-dnd';
4 | import Backend from 'react-dnd-html5-backend';
5 | import { SaveOutlined } from '@ant-design/icons';
6 | import styles from './Layout.less';
7 | import { makerContext } from '@/store/Maker';
8 | import SchemaForm, { createAsyncFormActions, SchemaMarkupField as Field } from '@formily/antd';
9 |
10 | interface Props {
11 | left: React.ReactNode;
12 | center: React.ReactNode;
13 | right: React.ReactNode;
14 | }
15 |
16 | const Layout: React.SFC = props => {
17 | const maker = React.useContext(makerContext)!;
18 | const { left, center, right } = props;
19 | const [visible, setVisible] = React.useState(false);
20 | const actions = React.useRef(createAsyncFormActions()).current;
21 | return (
22 |
23 |
24 |
25 |
33 | 未命名表单
34 |
35 |
36 |
37 | }
39 | shape="round"
40 | type="primary"
41 | onClick={() => {
42 | maker.saveFormData();
43 | }}
44 | >
45 | 保存
46 |
47 |
48 |
49 |
50 |
51 |
52 |
{left}
53 |
{center}
54 |
{right}
55 |
56 |
57 |
58 | );
59 | };
60 |
61 | export default Layout;
62 |
--------------------------------------------------------------------------------
/src/pages/layouts/WidgeList/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Widge from '../../../components/Widge';
3 | import { Tabs, Button } from 'antd';
4 | import { Widges } from '@/widge';
5 | import { Draggable, DragDropContext } from 'react-beautiful-dnd';
6 |
7 | interface Data {
8 | label: string;
9 | type: string;
10 | icon: string;
11 | }
12 |
13 | const { TabPane } = Tabs;
14 |
15 | const WidgeList = () => {
16 | return (
17 |
18 |
19 |
20 | {Widges.map((x, index) => (
21 |
22 | ))}
23 |
24 |
25 |
26 | );
27 | };
28 |
29 | export default WidgeList;
30 |
--------------------------------------------------------------------------------
/src/schemajson.ts:
--------------------------------------------------------------------------------
1 | export const BASE = {
2 | type: 'object',
3 | properties: {
4 | title: {
5 | title: '标题',
6 | type: 'string',
7 | },
8 | placeholder: {
9 | title: '占位内容',
10 | type: 'string',
11 | },
12 | require: {
13 | title: '必填',
14 | type: 'Switch',
15 | },
16 | disabled: {
17 | title: '禁用',
18 | type: 'Switch',
19 | },
20 | },
21 | };
22 |
23 | export const DndInput = {
24 | type: 'object',
25 | properties: {
26 | title: {
27 | title: '标题',
28 | type: 'string',
29 | },
30 | placeholder: {
31 | title: '占位内容',
32 | type: 'string',
33 | },
34 | required: {
35 | title: '必填',
36 | type: 'Switch',
37 | },
38 | disabled: {
39 | title: '禁用',
40 | type: 'Switch',
41 | },
42 | },
43 | };
44 |
45 | export const DndDatePicker = {
46 | type: 'object',
47 | properties: {
48 | title: {
49 | title: '标题',
50 | type: 'string',
51 | },
52 | placeholder: {
53 | title: '占位内容',
54 | type: 'string',
55 | },
56 | required: {
57 | title: '必填',
58 | type: 'Switch',
59 | },
60 | disabled: {
61 | title: '禁用',
62 | type: 'Switch',
63 | },
64 | },
65 | };
66 |
67 | export const DndInputNumber = {
68 | type: 'object',
69 | properties: {
70 | title: {
71 | title: '标题',
72 | type: 'string',
73 | },
74 | placeholder: {
75 | title: '占位内容',
76 | type: 'string',
77 | },
78 | required: {
79 | title: '必填',
80 | type: 'Switch',
81 | },
82 | disabled: {
83 | title: '禁用',
84 | type: 'Switch',
85 | },
86 | },
87 | };
88 |
89 | export const DndTextarea = {
90 | type: 'object',
91 | properties: {
92 | title: {
93 | title: '标题',
94 | type: 'string',
95 | },
96 | placeholder: {
97 | title: '占位内容',
98 | type: 'string',
99 | },
100 | required: {
101 | title: '必填',
102 | type: 'Switch',
103 | },
104 | disabled: {
105 | title: '禁用',
106 | type: 'Switch',
107 | },
108 | },
109 | };
110 |
111 | export const DndSelect = {
112 | type: 'object',
113 | properties: {
114 | title: {
115 | title: '标题',
116 | type: 'string',
117 | },
118 | placeholder: {
119 | title: '占位内容',
120 | type: 'string',
121 | },
122 | required: {
123 | title: '必填',
124 | type: 'Switch',
125 | },
126 | disabled: {
127 | title: '禁用',
128 | type: 'Switch',
129 | },
130 | enum: {
131 | title: '简单数据',
132 | type: 'Options',
133 | },
134 | },
135 | };
136 |
137 | export const DndCheckbox = {
138 | type: 'object',
139 | properties: {
140 | title: {
141 | title: '标题',
142 | type: 'string',
143 | },
144 | placeholder: {
145 | title: '占位内容',
146 | type: 'string',
147 | },
148 | required: {
149 | title: '必填',
150 | type: 'Switch',
151 | },
152 | disabled: {
153 | title: '禁用',
154 | type: 'Switch',
155 | },
156 | enum: {
157 | title: '简单数据',
158 | type: 'Options',
159 | },
160 | },
161 | };
162 |
163 | export const DndRadio = {
164 | type: 'object',
165 | properties: {
166 | title: {
167 | title: '标题',
168 | type: 'string',
169 | },
170 | placeholder: {
171 | title: '占位内容',
172 | type: 'string',
173 | },
174 | required: {
175 | title: '必填',
176 | type: 'Switch',
177 | },
178 | disabled: {
179 | title: '禁用',
180 | type: 'Switch',
181 | },
182 | enum: {
183 | title: '简单数据',
184 | type: 'Options',
185 | },
186 | },
187 | };
188 |
189 | export const DndSwitch = {
190 | type: 'object',
191 | properties: {
192 | title: {
193 | title: '标题',
194 | type: 'string',
195 | },
196 | required: {
197 | title: '必填',
198 | type: 'Switch',
199 | },
200 | disabled: {
201 | title: '禁用',
202 | type: 'Switch',
203 | },
204 | },
205 | };
206 |
207 | export const DndRangePicker = {
208 | type: 'object',
209 | properties: {
210 | title: {
211 | title: '标题',
212 | type: 'string',
213 | },
214 | required: {
215 | title: '必填',
216 | type: 'Switch',
217 | },
218 | disabled: {
219 | title: '禁用',
220 | type: 'Switch',
221 | },
222 | },
223 | };
224 |
--------------------------------------------------------------------------------
/src/service/data.d.ts:
--------------------------------------------------------------------------------
1 | interface FMComponent {
2 | id?: string;
3 | name?: string;
4 | type?: string;
5 | }
6 |
7 | interface FMFieldList {
8 | componentId?: string;
9 | value?: string | number;
10 | }
11 |
12 | interface FormEntity {
13 | addUserId?: string;
14 | componentList?: FMComponent[];
15 | name?: string;
16 | style?: string;
17 | remark?: string;
18 | }
19 |
20 | interface IPagenationParams {
21 | pageNum: number;
22 | pageSize: number;
23 | }
24 |
25 | interface FMFormData {
26 | addUserId?: string;
27 | fieldList?: FMFieldList[];
28 | formId?: string;
29 | }
30 |
--------------------------------------------------------------------------------
/src/service/form.ts:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | export async function add(data: FormEntity) {
4 | return request('/form', { method: 'post', data: data });
5 | }
6 |
7 | export async function getById(formId: string) {
8 | return request(`/form/${formId}`);
9 | }
10 |
11 | export async function update(data: FormEntity) {
12 | return request('/form', { method: 'put', data });
13 | }
14 |
15 | export async function deleteById(formId: string) {
16 | return request(`/form/${formId}`, { method: 'delete' });
17 | }
18 |
19 | export async function getPaged(params: IPagenationParams) {
20 | return request(`/form`, { params });
21 | }
22 |
23 | export async function submit(data: FMFormData) {
24 | return request(`/form/data`, { method: 'post', data });
25 | }
26 |
--------------------------------------------------------------------------------
/src/service/formData.ts:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request';
2 |
3 | interface PaginationParams extends IPagenationParams {
4 | formId: string;
5 | }
6 |
7 | export async function getPaged(params: PaginationParams) {
8 | return request(`/form/data`, { method: 'get', params });
9 | }
10 |
--------------------------------------------------------------------------------
/src/store/Maker.ts:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { observable, action, toJS, autorun } from 'mobx';
3 | import uuid, { v4 as uuidv4 } from 'uuid';
4 | import * as _ from 'lodash';
5 | import * as formSv from '@/service/form';
6 | import { message } from 'antd';
7 | import { getGUID } from '@/utils/utils';
8 |
9 | export interface MakerItemProps {
10 | label: string;
11 | required?: boolean;
12 | placeholder?: string;
13 | disabled?: boolean;
14 | default?: string | number; //默认值
15 | datePicker?: string; //时间选择器类型
16 | }
17 |
18 | interface Target {
19 | data?: any;
20 | index: number;
21 | }
22 |
23 | export class Maker {
24 | @observable FieldPropsList: any[] = [];
25 | @observable MakerItems: [] = [];
26 | @observable target: Target | undefined = undefined;
27 |
28 | @observable selected: any | undefined = undefined;
29 |
30 | @observable formId: string | undefined = undefined;
31 |
32 | constructor() {}
33 |
34 | @action
35 | resetFormId = (formId?: string) => {
36 | this.formId = formId;
37 | };
38 |
39 | @action
40 | submitFormData = (data: { [key: string]: string }) => {
41 | const fieldList: FMFieldList[] = [];
42 | Object.keys(data).forEach(key =>
43 | fieldList.push({ componentId: key, value: JSON.stringify(data[key]) }),
44 | );
45 | console.log(fieldList);
46 | const formData: FMFormData = {
47 | addUserId: '123',
48 | fieldList,
49 | formId: this.formId,
50 | };
51 | return formSv.submit(formData).then(this.resetFormId);
52 | };
53 |
54 | @action
55 | appendItem(item: any) {
56 | item.fieldProps.name = getGUID();
57 | this.FieldPropsList.push(item);
58 | }
59 |
60 | @action
61 | isCanAppend() {
62 | return this.target === undefined;
63 | }
64 |
65 | @action
66 | resetTarget(t: Target | undefined) {
67 | this.target = t;
68 | }
69 |
70 | @action
71 | resetMakerItems(makerItems: any[]) {
72 | this.FieldPropsList = makerItems;
73 | }
74 |
75 | @action
76 | deleteMakerItemById = (uuid: string) => {
77 | this.FieldPropsList = this.FieldPropsList.filter(({ fieldProps }) => fieldProps.name !== uuid);
78 | };
79 |
80 | @action
81 | resetSelected = (item: any) => {
82 | this.selected = item;
83 | };
84 |
85 | @action
86 | isSelected = (item: any) => {
87 | return this.selected?.name === item.name;
88 | };
89 |
90 | @action
91 | mutePrpos = (props: MakerItemProps) => {
92 | if (!!this.selected)
93 | this.FieldPropsList = this.FieldPropsList.map(x => {
94 | if (x.fieldProps.name === this.selected?.fieldProps.name) {
95 | return { ...x, fieldProps: props };
96 | }
97 | return x;
98 | }) as any;
99 | };
100 |
101 | @action
102 | addCopy = () => {
103 | let clone = _.cloneDeep(this.selected);
104 | clone.fieldProps.name = uuidv4();
105 | this.FieldPropsList.push(clone!);
106 | };
107 |
108 | @action
109 | clear = () => {
110 | this.FieldPropsList = [];
111 | };
112 |
113 | @action
114 | getSchema = () => {
115 | if (!!this.FieldPropsList && this.FieldPropsList.length === 0) {
116 | return undefined;
117 | }
118 |
119 | let result = {
120 | type: 'object',
121 | properties: {} as any,
122 | };
123 |
124 | this.FieldPropsList.forEach(
125 | ({ fieldProps }) => (result.properties[fieldProps.name] = { ...fieldProps }),
126 | );
127 | return result;
128 | };
129 |
130 | @action
131 | getDndSchema = () => {
132 | if (!!this.FieldPropsList && this.FieldPropsList.length === 0) {
133 | return undefined;
134 | }
135 |
136 | let result = {
137 | type: 'object',
138 | properties: {} as any,
139 | };
140 |
141 | return result;
142 | };
143 | @action
144 | saveFormData = (name?: string) => {
145 | const componentList: FMComponent[] = this.FieldPropsList.map(({ fieldProps, type }) => ({
146 | id: fieldProps.name,
147 | name: fieldProps.title,
148 | type: type,
149 | }));
150 | const formEntity: FormEntity = {
151 | addUserId: '123',
152 | componentList,
153 | name: name || getGUID(),
154 | style: JSON.stringify(this.FieldPropsList),
155 | remark: 'remark',
156 | };
157 |
158 | return formSv.add(formEntity).then(() => message.success('成功'));
159 | };
160 | }
161 |
162 | export const makerContext = React.createContext(null);
163 |
--------------------------------------------------------------------------------
/src/store/data.d.ts:
--------------------------------------------------------------------------------
1 | interface BasicProps {
2 | required?: boolean;
3 | disabled?: boolean;
4 | label?: string;
5 | placeholder?: string;
6 | readonly?: string;
7 | default?: string | any;
8 | }
9 |
10 | interface DatePickerProps extends BasicProps {
11 | picker?: string;
12 | format?: string; //日期格式 默认 yyyy-MM-dd
13 | timestamp?: boolean; //是否获取时间戳
14 | }
15 |
16 | interface SelectProps extends BasicProps {
17 | mode: string;
18 | enum: any[];
19 | }
20 |
--------------------------------------------------------------------------------
/src/utils/data.d.ts:
--------------------------------------------------------------------------------
1 | interface IWidge {
2 | icon: string;
3 | label: string;
4 | type: string;
5 | fieldProps: any;
6 | }
7 |
--------------------------------------------------------------------------------
/src/utils/request.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * request 网络请求工具
3 | * 更详细的 api 文档: https://github.com/umijs/umi-request
4 | */
5 | import { extend, RequestOptionsInit } from 'umi-request';
6 | import { notification } from 'antd';
7 | import { router } from 'umi';
8 |
9 | const codeMessage = {
10 | 200: '服务器成功返回请求的数据。',
11 | 201: '新建或修改数据成功。',
12 | // 201: '服务器错误',
13 | 202: '一个请求已经进入后台排队(异步任务)。',
14 | 204: '删除数据成功。',
15 | 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
16 | 401: '用户没有权限(令牌、用户名、密码错误)。',
17 | 403: '用户得到授权,但是访问是被禁止的。',
18 | 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
19 | 406: '请求的格式不可得。',
20 | 410: '请求的资源被永久删除,且不会再得到的。',
21 | 422: '当创建一个对象时,发生一个验证错误。',
22 | 500: '服务器发生错误,请检查服务器。',
23 | 502: '网关错误。',
24 | 503: '服务不可用,服务器暂时过载或维护。',
25 | 504: '网关超时。',
26 | };
27 |
28 | /**
29 | * 异常处理程序
30 | */
31 | const errorHandler = (error: { response: Response }): Response => {
32 | const { response } = error;
33 | if (response && response.status) {
34 | const errorText = (codeMessage as any)[response.status] || response.statusText;
35 | const { status, url } = response;
36 | notification.error({
37 | message: `请求错误 ${status}: ${url}`,
38 | description: errorText,
39 | });
40 | }
41 | return response;
42 | };
43 |
44 | // export const prefix =
45 | // process.env.NODE_ENV === 'development' ? '' : 'http://47.104.131.14/digitcons/v1';
46 |
47 | export const prefix = 'http://47.104.131.14/wisdomsite/v1';
48 | // export const prefix = 'http://39.104.81.4/wisdomsite/v1'
49 |
50 | // export const prefix = 'http://www.lanlan.live:8085/wisdomsite/v1'
51 | /**
52 | * 配置request请求时的默认参数
53 | */
54 | export const urequest = extend({
55 | prefix: prefix,
56 | errorHandler, // 默认错误处理
57 | credentials: 'include', // 默认请求是否带上cookie
58 | });
59 |
60 | export const request = (url: string, options?: RequestOptionsInit) => {
61 | return new Promise(async (resolve, reject) => {
62 | const res = await urequest(url, options);
63 | if (res === null) {
64 | reject('未知错误');
65 | return;
66 | }
67 | const error = handleStatusError(res.status, url, res.message);
68 |
69 | if (error) reject(error);
70 |
71 | const boxingRes = boxingResponse(res);
72 | resolve(boxingRes);
73 | }).catch(error => {
74 | throw error;
75 | });
76 | };
77 |
78 | const handleStatusError = (status: number, url?: string, msg?: string): string | undefined => {
79 | const errorConfig = (BACKENDSTATUSERRORCONFIG as any)[status] || undefined;
80 | if (Array.isArray(errorConfig)) {
81 | const [defaultMsg, fn] = errorConfig;
82 | if (typeof fn === 'function') {
83 | fn(msg || defaultMsg, url);
84 | }
85 | return msg;
86 | }
87 |
88 | return errorConfig;
89 | };
90 |
91 | const boxingResponse = (res: any) => {
92 | const data = res.data;
93 | if (data && data.pageTool) {
94 | const pageTool = data.pageTool;
95 | return {
96 | dataList: data.beanList || [],
97 | meta: {
98 | pageNum: pageTool.pageNum,
99 | pageSize: pageTool.pageTool,
100 | total: pageTool.totalSize,
101 | },
102 | };
103 | }
104 | return res;
105 | };
106 |
107 | const BACKENDSTATUSERRORCONFIG = {
108 | 125: [
109 | 'token error!',
110 | () => {
111 | router.push('/user/login');
112 | },
113 | ],
114 | 201: [
115 | '后台服务器异常请查阅日志!',
116 | (errorText: string, url: string) => {
117 | notification.error({
118 | message: `请求错误 ${status}: ${url}`,
119 | description: errorText,
120 | });
121 | },
122 | ],
123 | 116: [
124 | '项目进度id不能为空',
125 | (errorText: string, url: string) => {
126 | notification.error({
127 | message: `请求错误 ${status}: ${url}`,
128 | description: errorText,
129 | });
130 | },
131 | ],
132 | 121: [
133 | '',
134 | (errorText: string, url: string) => {
135 | notification.error({
136 | message: `请求错误 ${status}: ${url}`,
137 | description: errorText,
138 | });
139 | },
140 | ],
141 | 10: ['', ''],
142 | };
143 |
144 | // 中间件,对请求前、响应后做处理
145 | urequest.use(async (ctx, next) => {
146 | const { req } = ctx;
147 |
148 | req.options.headers = {
149 | auth_token: 'd7dda732508242669ba1c1506935b1e8',
150 | };
151 |
152 | await next();
153 | const { res } = ctx;
154 |
155 | // if (process.env.NODE_ENV === 'development') {
156 | // console.log(`API: ${req.url.replace(prefix, '')} \r\n返回的数据: `, res.data, ' \r\n');
157 | // console.log(`\r\n`);
158 | // }
159 | });
160 |
161 | export default request;
162 |
--------------------------------------------------------------------------------
/src/utils/utils.ts:
--------------------------------------------------------------------------------
1 | import { v4 as uuidV4 } from 'uuid';
2 | export const getItemStyle = (isDragging: any, draggableStyle: any) => ({
3 | // some basic styles to make the items look a bit nicer
4 | // userSelect: 'none',
5 |
6 | // change background colour if dragging
7 | // background: isDragging ? 'lightgreen' : 'red',
8 |
9 | // styles we need to apply on draggables
10 | ...draggableStyle,
11 | });
12 |
13 | export const getListStyle = (isDraggingOver: any) => ({
14 | // background: isDraggingOver ? 'lightblue' : 'grey',
15 | });
16 |
17 | export const getGUID = () => {
18 | return uuidV4().replace(/-/g, '');
19 | };
20 |
--------------------------------------------------------------------------------
/src/widge.ts:
--------------------------------------------------------------------------------
1 | import { ItemTypes } from './contants';
2 | import { getGUID } from './utils/utils';
3 |
4 | export const Widges = [
5 | {
6 | label: '单行文本',
7 | type: ItemTypes.INPUT,
8 | icon: 'anticoninput',
9 | fieldProps: {
10 | 'x-component': 'string',
11 | title: '单行文本',
12 | },
13 | },
14 | {
15 | label: '数字输入框',
16 | type: ItemTypes.INPUTNUMBER,
17 | icon: 'anticonfuhao-shuzishurukuang',
18 | fieldProps: {
19 | 'x-component': 'NumberPicker',
20 | title: '数字输入框',
21 | },
22 | },
23 | {
24 | label: '多行文本',
25 | type: ItemTypes.TEXTAREA,
26 | icon: 'anticontextareabt_back',
27 | uuid: getGUID(),
28 | fieldProps: {
29 | 'x-component': 'textarea',
30 | title: '多行文本',
31 | },
32 | },
33 | {
34 | label: '下拉选择器',
35 | type: ItemTypes.SELECT,
36 | icon: 'anticondrop-down',
37 | uuid: getGUID(),
38 | fieldProps: {
39 | 'x-component': 'string',
40 | title: '下拉选择器',
41 | enum: [{ label: 'option1', value: 'option1' }],
42 | },
43 | },
44 | {
45 | label: '日期选择器',
46 | type: ItemTypes.DATEPICKER,
47 | icon: 'anticonmdatepicker',
48 | uuid: getGUID(),
49 | fieldProps: {
50 | type: 'daterange',
51 | title: '日期选择器',
52 | picker: 'date',
53 | },
54 | },
55 | {
56 | label: '日期范围选择',
57 | type: ItemTypes.RANGPICKER,
58 | icon: 'anticonmdatepicker',
59 | uuid: getGUID(),
60 | fieldProps: {
61 | type: 'RangePicker',
62 | title: '日期范围选择器',
63 | picker: 'date',
64 | },
65 | },
66 | {
67 | label: '多选框',
68 | type: ItemTypes.CHECKBOX,
69 | icon: 'anticonduoxuankuang',
70 | uuid: getGUID(),
71 | fieldProps: {
72 | 'x-component': 'CheckboxGroup',
73 | title: '多选框',
74 | enum: [
75 | { label: 'One', value: '1' },
76 | { label: 'Two', value: '2' },
77 | { label: 'Three', value: '3' },
78 | { label: 'Four', value: '4' },
79 | ],
80 | },
81 | },
82 | {
83 | label: '单选框',
84 | type: ItemTypes.RADIO,
85 | icon: 'anticondanxuankuangxuanzhong',
86 | uuid: getGUID(),
87 | fieldProps: {
88 | 'x-component': 'RadioGroup',
89 | title: '单选框',
90 | enum: [
91 | { label: 'One', value: '1' },
92 | { label: 'Two', value: '2' },
93 | { label: 'Three', value: '3' },
94 | { label: 'Four', value: '4' },
95 | ],
96 | },
97 | },
98 | {
99 | label: '开关按钮',
100 | type: ItemTypes.SWITCH,
101 | icon: 'anticonkaiguananniu',
102 | uuid: getGUID(),
103 | fieldProps: {
104 | 'x-component': 'Switch',
105 | title: '开关按钮',
106 | },
107 | },
108 | ];
109 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "lib": ["dom", "dom.iterable", "esnext"],
7 | "skipLibCheck": true,
8 | "importHelpers": true,
9 | "jsx": "react",
10 | "esModuleInterop": true,
11 | "sourceMap": true,
12 | "baseUrl": ".",
13 | "strict": true,
14 | "experimentalDecorators": true,
15 | "emitDecoratorMetadata": true,
16 | "paths": {
17 | "@/*": ["src/*"],
18 | "@tmp/*": ["src/pages/.umi/*"],
19 | "@@/*": ["src/.umi/*"]
20 | },
21 | "allowSyntheticDefaultImports": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.css';
2 | declare module '*.png';
3 | declare module '*.less';
4 |
--------------------------------------------------------------------------------