├── src ├── QuestionnairAnswer │ ├── index.less │ └── index.js ├── .DS_Store ├── index.js ├── main.js ├── Questionnair │ ├── index.less │ └── index.js ├── QuestionnairContent │ ├── index.less │ └── index.js ├── QuestionnairSiderbar │ ├── index.less │ └── index.js └── QuestionnairEditor │ ├── index.less │ └── index.js ├── .gitignore ├── .DS_Store ├── assets ├── .DS_Store ├── iconfonts │ ├── .DS_Store │ ├── iconfont.eot │ ├── iconfont.ttf │ ├── iconfont.woff │ ├── iconfont.css │ └── iconfont.svg └── scale_default.png ├── libs ├── .DS_Store ├── Dropdown │ ├── index.less │ └── index.js ├── ContentEditable │ ├── index.less │ └── index.js ├── Shake │ ├── index.less │ └── index.js ├── DragSort │ ├── index.less │ ├── index.js │ └── example.js ├── Button │ ├── index.less │ └── index.js ├── Input │ ├── index.less │ └── index.js ├── Checkbox │ ├── index.less │ └── index.js ├── Radio │ ├── index.less │ └── index.js └── Dialog │ ├── index.less │ └── index.js ├── .babelrc ├── react-questionnair.png ├── dist ├── 29933c03dca9629dd8bfef50bec5005f.png ├── 3f8467b01369f58b0a67ac2ed08c8f3a.eot ├── ab85a97f51f177206f0635614657e685.ttf └── index.html ├── utils └── utils.js ├── index.html ├── bin └── dev-server.js ├── package.json ├── webpack └── webpack.config.js └── README.md /src/QuestionnairAnswer/index.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | npm-debug.log* -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/.DS_Store -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/src/.DS_Store -------------------------------------------------------------------------------- /assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/assets/.DS_Store -------------------------------------------------------------------------------- /libs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/libs/.DS_Store -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015", 4 | "react", 5 | "stage-1" 6 | ], 7 | } -------------------------------------------------------------------------------- /libs/Dropdown/index.less: -------------------------------------------------------------------------------- 1 | :global{ 2 | .wowjoy-select { 3 | display: inline-block; 4 | } 5 | }; -------------------------------------------------------------------------------- /react-questionnair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/react-questionnair.png -------------------------------------------------------------------------------- /assets/iconfonts/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/assets/iconfonts/.DS_Store -------------------------------------------------------------------------------- /assets/scale_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/assets/scale_default.png -------------------------------------------------------------------------------- /assets/iconfonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/assets/iconfonts/iconfont.eot -------------------------------------------------------------------------------- /assets/iconfonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/assets/iconfonts/iconfont.ttf -------------------------------------------------------------------------------- /assets/iconfonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/assets/iconfonts/iconfont.woff -------------------------------------------------------------------------------- /libs/ContentEditable/index.less: -------------------------------------------------------------------------------- 1 | :global { 2 | .contentEditable { 3 | outline: none; 4 | line-height: 36px; 5 | } 6 | } -------------------------------------------------------------------------------- /dist/29933c03dca9629dd8bfef50bec5005f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/dist/29933c03dca9629dd8bfef50bec5005f.png -------------------------------------------------------------------------------- /dist/3f8467b01369f58b0a67ac2ed08c8f3a.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/dist/3f8467b01369f58b0a67ac2ed08c8f3a.eot -------------------------------------------------------------------------------- /dist/ab85a97f51f177206f0635614657e685.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandly/react-questionnair/HEAD/dist/ab85a97f51f177206f0635614657e685.ttf -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Questionnair from './Questionnair'; 2 | import Editor from './QuestionnairEditor'; 3 | import Answer from './QuestionnairAnswer'; 4 | import 'assets/iconfonts/iconfont.css'; 5 | 6 | Questionnair.Editor = Editor; 7 | Questionnair.Answer = Answer; 8 | 9 | export default Questionnair; -------------------------------------------------------------------------------- /utils/utils.js: -------------------------------------------------------------------------------- 1 | export default function uuid() { 2 | const s = []; 3 | const hexDigits = '0123456789abcdef'; 4 | for (let i = 0; i < 36; i += 1) { 5 | s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); 6 | } 7 | s[14] = '4'; 8 | s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); 9 | const id = s.join(''); 10 | return id; 11 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-questionnair 6 | 18 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /libs/Shake/index.less: -------------------------------------------------------------------------------- 1 | //animate 2 | @keyframes shake { 3 | from, to { 4 | transform: translate3d(0, 0, 0); 5 | } 6 | 7 | 10%, 30%, 50%, 70%, 90% { 8 | transform: translate3d(-8px, 0, 0); 9 | } 10 | 11 | 20%, 40%, 60%, 80% { 12 | transform: translate3d(8px, 0, 0); 13 | } 14 | } 15 | .shake-transition { 16 | height: 100%; 17 | width: 100%; 18 | } 19 | .shaked { 20 | animation-name: shake; 21 | animation-duration: 1s; 22 | animation-fill-mode: both; 23 | } 24 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-questionnair 6 | 18 | 19 | 20 |
21 | 22 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | render, 4 | } from 'react-dom'; 5 | import Questionnair from './index.js'; 6 | 7 | const index = require('./index'); 8 | 9 | const renderDom = (Component) => { 10 | render( 11 | , 12 | document.getElementById('app') 13 | ); 14 | }; 15 | renderDom(Questionnair); 16 | if (module.hot) { 17 | module.hot.accept('./index', () => { 18 | const QuestionnairEl = index.default; 19 | renderDom(QuestionnairEl); 20 | }); 21 | } -------------------------------------------------------------------------------- /src/Questionnair/index.less: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | user-select: none; 4 | font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; 5 | } 6 | .questionnair { 7 | display: flex; 8 | width: 100%; 9 | height: 100%; 10 | background: #f0f0f0; 11 | } 12 | :global { 13 | .title-inner { 14 | width: 700px; 15 | height: 45px; 16 | margin: 0 auto; 17 | background: #fff; 18 | display: flex; 19 | justify-content: center; 20 | align-items: center; 21 | border: 1px solid transparent; 22 | } 23 | } -------------------------------------------------------------------------------- /libs/DragSort/index.less: -------------------------------------------------------------------------------- 1 | :global { 2 | .item{ 3 | height: 35px; 4 | margin:10px; 5 | // background-color: #eee; 6 | // &:hover { 7 | // background-color: red; 8 | // } 9 | } 10 | .item-notdrag { 11 | height: 35px; 12 | margin:10px; 13 | background-color: #eee; 14 | 15 | } 16 | .inner { 17 | height: 100%; 18 | } 19 | .item.active{ 20 | //height: 35px; 21 | //margin:10px; 22 | opacity: 0; 23 | //background-color: #eee !important; 24 | } 25 | }; -------------------------------------------------------------------------------- /libs/Button/index.less: -------------------------------------------------------------------------------- 1 | :global{ 2 | .wowjoy-button { 3 | padding: 6px 20px; 4 | border: 1px solid #06aea6; 5 | margin: 0 10px; 6 | outline: none; 7 | cursor: pointer; 8 | font-size: 14px 9 | } 10 | .wowjoy-button__primary { 11 | background: #06aea6; 12 | color: #fff; 13 | } 14 | .wowjoy-button__normal { 15 | background: #fff; 16 | color: #06aea6; 17 | } 18 | .wowjoy-button__mini { 19 | padding: 4px; 20 | font-size: 12px; 21 | } 22 | .wowjoy-button__small { 23 | padding: 7px 9px; 24 | font-size: 12px; 25 | } 26 | .wowjoy-button__large { 27 | padding: 11px 19px; 28 | font-size: 16px; 29 | } 30 | }; -------------------------------------------------------------------------------- /libs/Input/index.less: -------------------------------------------------------------------------------- 1 | :global { 2 | .wowjoy-input { 3 | overflow: hidden; 4 | width: 100%; 5 | height: 100%; 6 | flex: 1; 7 | z-index: 5; 8 | display: inline-block; 9 | } 10 | .wowjoy-input__inner { 11 | width: 100%; 12 | height: 36px; 13 | border: 1px solid #ddd; 14 | outline: none; 15 | transition: all .3s; 16 | padding-left: 11px; 17 | font-size: 14px; 18 | color: rgb(102, 102, 102); 19 | &:focus { 20 | border-color: #06AEA6; 21 | } 22 | } 23 | .wowjoy-textarea__inner { 24 | width: 100%; 25 | border: 1px solid #ddd; 26 | outline: none; 27 | transition: all .3s; 28 | padding: 0 11px; 29 | font-size: 14px; 30 | color: rgb(102, 102, 102); 31 | &:focus { 32 | border-color: #06AEA6; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /bin/dev-server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * webpack-dev-server是一个小型的静态文件服务器,为webpack打包的资源文件提供Web服务 3 | */ 4 | const WebpackDevServer = require('webpack-dev-server'); 5 | const config = require('../webpack/webpack.config'); 6 | const webpack = require('webpack'); 7 | const path = require('path'); 8 | const compiler = webpack(config); 9 | const port = 9090; 10 | 11 | const server = new WebpackDevServer(compiler, { 12 | contentBase: path.resolve(__dirname, '../dist'), //默认会以根文件夹提供本地服务器,这里指定文件夹 13 | historyApiFallback: true, //在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html 14 | port: port, //如果省略,默认8080 15 | publicPath: "/", 16 | inline: true, // 自动刷新 17 | hot: true, // 开启热模块替换 18 | }); 19 | 20 | console.log('> Starting dev server...') 21 | server.listen(port, 'localhost', function(err) { 22 | if (err) throw err 23 | }) -------------------------------------------------------------------------------- /libs/Checkbox/index.less: -------------------------------------------------------------------------------- 1 | :global { 2 | .wowjoy-checkbox { 3 | cursor: pointer; 4 | display: inline-block; 5 | } 6 | input[type='checkbox']:checked { 7 | &+.wowjoy-checkbox__inner { 8 | border-color: #06aea6; 9 | &:before { 10 | content: '\2713'; 11 | color: #06aea6; 12 | position: absolute; 13 | top: 50%; 14 | left: 50%; 15 | transform: translate(-50%, -50%); 16 | } 17 | } 18 | } 19 | .wowjoy-checkbox__inner { 20 | position: relative; 21 | display: inline-block; 22 | width: 16px; 23 | height: 16px; 24 | background: #fff; 25 | border: 1px solid #DBDBDB; 26 | vertical-align: sub; 27 | margin-right: 5px; 28 | } 29 | .wowjoy-checkbox__text { 30 | display: inline-block; 31 | max-width: 80%; 32 | vertical-align: top; 33 | word-break: break-all; 34 | } 35 | } -------------------------------------------------------------------------------- /src/QuestionnairAnswer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const QuestionnairAnswer = ({ 4 | answer 5 | }) => { 6 | return ( 7 |
8 |
{`${index + 1}.${answer.type === 'input' ? answer.completionForwards : answer.title + ':'}`}
9 |
{typeof answer.answer[answer.type] !== 'string' ? ( 10 | typeof answer.answer[answer.type].optionValue !== 'string' ? ( 11 | answer.answer[answer.type].optionValue.map((item, index) => { 12 | return ( 13 | item && {item} 14 | ) 15 | }) 16 | ) : answer.answer[answer.type].optionValue 17 | ) : answer.answer[answer.type]}
18 |
19 | ); 20 | } 21 | 22 | export default QuestionnairAnswer; -------------------------------------------------------------------------------- /libs/Radio/index.less: -------------------------------------------------------------------------------- 1 | :global { 2 | .wowjoy-radio { 3 | cursor: pointer; 4 | display: inline-block; 5 | } 6 | input[type='radio']:checked { 7 | &+.wowjoy-radio__inner { 8 | border-color: #06aea6; 9 | &:before { 10 | content: ''; 11 | background: #06aea6; 12 | width: 8px; 13 | height: 8px; 14 | border-radius: 50%; 15 | position: absolute; 16 | top: 50%; 17 | left: 50%; 18 | transform: translate(-50%, -50%); 19 | } 20 | } 21 | } 22 | .wowjoy-radio__inner { 23 | position: relative; 24 | display: inline-block; 25 | width: 16px; 26 | height: 16px; 27 | border-radius: 50%; 28 | background: #fff; 29 | border: 1px solid #DBDBDB; 30 | vertical-align: sub; 31 | margin-right: 5px; 32 | } 33 | .wowjoy-radio__text { 34 | display: inline-block; 35 | max-width: 80%; 36 | vertical-align: top; 37 | word-break: break-all; 38 | } 39 | } -------------------------------------------------------------------------------- /libs/Dropdown/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.less'; 3 | 4 | class Select extends React.PureComponent { 5 | 6 | handleChange = (e) => { 7 | const { 8 | onChange, 9 | } = this.props; 10 | if (onChange) { 11 | onChange(e); 12 | }; 13 | } 14 | 15 | render() { 16 | const { 17 | name, 18 | value, 19 | options, 20 | } = this.props; 21 | return ( 22 |
23 | 33 |
34 | ); 35 | } 36 | } 37 | 38 | export default Select; -------------------------------------------------------------------------------- /libs/Radio/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.less'; 3 | 4 | class Radio extends React.PureComponent { 5 | 6 | handleChange = (e) => { 7 | const { 8 | onChange, 9 | } = this.props; 10 | if (onChange) { 11 | onChange(e); 12 | }; 13 | } 14 | 15 | render() { 16 | const { 17 | defaultChecked, 18 | value, 19 | name, 20 | label, 21 | style, 22 | } = this.props; 23 | return ( 24 | 35 | ); 36 | } 37 | } 38 | 39 | export default Radio; -------------------------------------------------------------------------------- /libs/Button/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.less'; 3 | 4 | class Button extends React.PureComponent { 5 | static defaultProps = { 6 | disabled: false, 7 | type: '', 8 | size: '', 9 | } 10 | 11 | handleClick = (e) => { 12 | const { 13 | onClick, 14 | } = this.props; 15 | if (onClick) { 16 | onClick(); 17 | }; 18 | } 19 | 20 | render() { 21 | const { 22 | type, 23 | size, 24 | disabled, 25 | children, 26 | onClick, 27 | ...otherProps, 28 | } = this.props; 29 | const buttonType = type ? `wowjoy-button__${type}` : ''; 30 | const buttonSize = size ? `wowjoy-button__${size}` : ''; 31 | return ( 32 | 38 | ); 39 | } 40 | } 41 | 42 | export default Button; -------------------------------------------------------------------------------- /libs/Shake/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.less'; 3 | 4 | class ShakeTransition extends React.PureComponent { 5 | state = { 6 | shake: false, 7 | } 8 | 9 | componentWillReceiveProps(nextProps) { 10 | if (nextProps.shake !== this.props.shake) { 11 | this.setState({ 12 | shake: true, 13 | }); 14 | this.timerID = setTimeout(() => this.triggerShake(), 1000); 15 | }; 16 | } 17 | 18 | triggerShake = () => { 19 | this.setState({ 20 | shake: false, 21 | }); 22 | } 23 | 24 | componentWillUnmount() { 25 | clearTimeout(this.timerID); 26 | } 27 | 28 | render() { 29 | const { 30 | children, 31 | } = this.props; 32 | const { 33 | shake, 34 | } = this.state; 35 | return ( 36 |
37 | {this.props.children} 38 |
39 | ); 40 | } 41 | } 42 | 43 | export default ShakeTransition; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-questionnair", 3 | "version": "v1.0.1", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "dev": "node bin/dev-server", 8 | "build": "webpack --config webpack/webpack.config.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "babel-core": "^6.26.3", 14 | "babel-loader": "^7.1.4", 15 | "babel-preset-es2015": "^6.24.1", 16 | "babel-preset-react": "^6.24.1", 17 | "babel-preset-stage-1": "^6.24.1", 18 | "react": "^16.4.1", 19 | "react-dom": "^16.4.1" 20 | }, 21 | "devDependencies": { 22 | "babel-eslint": "^8.2.6", 23 | "css-loader": "^0.28.11", 24 | "file-loader": "^1.1.11", 25 | "html-webpack-plugin": "^3.2.0", 26 | "less": "^3.0.4", 27 | "less-loader": "^4.1.0", 28 | "style-loader": "^0.21.0", 29 | "url-loader": "^1.0.1", 30 | "webpack": "^4.15.0", 31 | "webpack-cli": "^3.0.8", 32 | "webpack-dev-server": "^3.1.4" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /libs/Checkbox/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.less'; 3 | 4 | class Checkbox extends React.PureComponent { 5 | static defaultProps = { 6 | value: '', 7 | name: '', 8 | } 9 | 10 | handleChange = (e) => { 11 | const { 12 | onChange, 13 | index, 14 | } = this.props; 15 | if (onChange) { 16 | onChange(e, index); 17 | }; 18 | } 19 | 20 | render() { 21 | const { 22 | defaultChecked, 23 | value, 24 | name, 25 | index, 26 | label, 27 | style, 28 | } = this.props; 29 | return ( 30 | 42 | ); 43 | } 44 | } 45 | 46 | export default Checkbox; -------------------------------------------------------------------------------- /libs/Dialog/index.less: -------------------------------------------------------------------------------- 1 | :global { 2 | .wowjoy-dialog { 3 | position: absolute; 4 | top: 0; 5 | left: 0; 6 | right: 0; 7 | bottom: 0; 8 | background: rgba(0,0,0,0.30); 9 | //visibility: hidden; 10 | display: none; 11 | //transition: all .3s; 12 | z-index: 10; 13 | } 14 | .wowjoy-dialog__fadeIn { 15 | display: block; 16 | } 17 | .wowjoy-dialog__inner { 18 | background: #FFFFFF; 19 | box-shadow: 0 0 4px 0 rgba(0,0,0,0.20); 20 | border-radius: 3px; 21 | padding: 10px 20px; 22 | width: 40%; 23 | max-width: 500px; 24 | min-width: 300px; 25 | position: absolute; 26 | top: 50%; 27 | left: 50%; 28 | transform: translate(-50%, -50%); 29 | //opacity: 0; 30 | //transition: all .3s; 31 | } 32 | .wowjoy-dialog__slideDown { 33 | opacity: 1; 34 | transform: translateY(-50%); 35 | } 36 | .wowjoy-dialog__header { 37 | margin-bottom: 15px; 38 | font-family: PingFangSC-Medium; 39 | font-size: 16px; 40 | color: #333333; 41 | } 42 | .wowjoy-dialog__footer { 43 | height: 40px; 44 | width: 100%; 45 | display: flex; 46 | align-items: center; 47 | justify-content: center; 48 | } 49 | }; -------------------------------------------------------------------------------- /src/QuestionnairContent/index.less: -------------------------------------------------------------------------------- 1 | .questionnair-page { 2 | flex: 1; 3 | background: #fff; 4 | box-shadow: 0 3px 4px 0 rgba(202,202,202,0.50); 5 | margin-left: 20px; 6 | overflow: auto; 7 | position: absolute; 8 | left: 170px; 9 | right: 20px; 10 | top: 20px; 11 | bottom: 20px; 12 | width: 1000px; 13 | margin: auto; 14 | } 15 | .questionnair-page-banner { 16 | height: 46px; 17 | width: 700px; 18 | margin: 0 auto; 19 | border-bottom: 1px solid #DBDBDB; 20 | display: flex; 21 | align-items: center; 22 | justify-content: flex-end; 23 | } 24 | .banner-text { 25 | cursor: pointer; 26 | display: inline-block; 27 | color: #999; 28 | } 29 | .questionnair-page-title { 30 | margin: 10px 0; 31 | width: 100%; 32 | padding: 10px 0; 33 | border-top: 1px solid transparent; 34 | border-bottom: 1px solid transparent; 35 | &:hover { 36 | border-color: #DBDBDB; 37 | background: #FAFAFA; 38 | :global { 39 | .title-inner { 40 | border-color: #DBDBDB; 41 | } 42 | }; 43 | } 44 | } 45 | .questionnair-page-content { 46 | width: 100%; 47 | } 48 | .questionnair-page-default { 49 | display: flex; 50 | align-items: center; 51 | justify-content: center; 52 | flex-direction: column; 53 | position: absolute; 54 | top: 45%; 55 | left: 50%; 56 | transform: translate(-50%, -50%); 57 | } 58 | .page-default-text { 59 | font-size: 16px; 60 | color: #999; 61 | margin-top: 20px; 62 | } -------------------------------------------------------------------------------- /libs/Dialog/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Button from 'libs/Button'; 3 | import './index.less' 4 | 5 | class Dialog extends React.PureComponent { 6 | state = { 7 | visible: this.props.visible, 8 | } 9 | 10 | componentWillReceiveProps(nextProps) { 11 | if (nextProps.visible !== this.props.visible) { 12 | this.setState({ 13 | visible: nextProps.visible, 14 | }); 15 | }; 16 | } 17 | 18 | confirm = () => { 19 | const { 20 | onConfirm, 21 | } = this.props; 22 | if (onConfirm) { 23 | onConfirm(); 24 | }; 25 | } 26 | 27 | cancel = () => { 28 | const { 29 | onCancel, 30 | } = this.props; 31 | if (onCancel) { 32 | onCancel(); 33 | }; 34 | } 35 | 36 | render() { 37 | const { 38 | title, 39 | children, 40 | onCancel, 41 | onConfirm, 42 | } = this.props; 43 | const { 44 | visible, 45 | } = this.state; 46 | const fade = visible ? 'wowjoy-dialog__fadeIn' : ''; 47 | return ( 48 |
49 |
50 |
51 | {title} 52 |
53 |
54 | {children} 55 |
56 |
57 | 58 | 59 |
60 |
61 |
62 | ); 63 | } 64 | } 65 | 66 | export default Dialog; -------------------------------------------------------------------------------- /src/QuestionnairSiderbar/index.less: -------------------------------------------------------------------------------- 1 | .questionnair-siderbar { 2 | position: absolute; 3 | bottom: 20px; 4 | top: 20px; 5 | left: 20px; 6 | width: 210px; 7 | display: flex; 8 | flex-direction: column; 9 | } 10 | .siderbar-tab { 11 | width: 100%; 12 | height: 30px; 13 | display: flex; 14 | position: relative; 15 | z-index: 1; 16 | } 17 | .tab-item { 18 | flex: 1; 19 | text-align: center; 20 | height: 30px; 21 | line-height: 30px; 22 | color: #666; 23 | background: #F7F7F7; 24 | border: 1px solid #e8e8e8; 25 | cursor: pointer; 26 | } 27 | .tab-item-active { 28 | box-shadow: 0 0 4px 0 rgba(202,202,202,0.50); 29 | border: 1px solid transparent; 30 | background: #fff; 31 | position: relative; 32 | &:before { 33 | content: ''; 34 | position: absolute; 35 | top: -1px; 36 | left: -1px; 37 | right: -1px; 38 | height: 2px; 39 | background-color: #06AEA6; 40 | z-index: 1; 41 | } 42 | } 43 | .siderbar-menu { 44 | flex: 1; 45 | box-shadow: 0 3px 4px 0 rgba(202,202,202,0.50); 46 | background: #fff; 47 | z-index: 2; 48 | } 49 | .siderbar-menu-content { 50 | width: 100%; 51 | } 52 | .siderbar-menu-icon { 53 | margin-right: 10px; 54 | } 55 | .siderbar-menu-editors { 56 | width: 168px; 57 | height: 36px; 58 | border: 1px solid #06AEA6; 59 | color: #06AEA6; 60 | padding-left: 8px; 61 | margin: 15px auto; 62 | cursor: pointer; 63 | display: flex; 64 | align-items: center; 65 | position: relative; 66 | } 67 | .siderbar-menu-summary { 68 | width: 100%; 69 | height: 36px; 70 | color: #06AEA6; 71 | padding-left: 30px; 72 | padding-right: 10px; 73 | margin: 0 auto; 74 | cursor: pointer; 75 | display: flex; 76 | align-items: center; 77 | position: relative; 78 | } 79 | .summary-text { 80 | overflow: hidden; 81 | text-overflow: ellipsis; 82 | white-space: nowrap; 83 | } 84 | .summary-drag-mask { 85 | position: absolute; 86 | top: 0; 87 | left: 0; 88 | right: 0; 89 | bottom: 0; 90 | } 91 | -------------------------------------------------------------------------------- /libs/DragSort/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | let curDragIndex = null; 4 | 5 | export default function DragSort(props) { 6 | let container = props.children; 7 | let draggable = props.draggable; 8 | 9 | function onChange(from, to) { 10 | let curValue = props.data; 11 | let newValue = arrMove(curValue, from, to); 12 | if (typeof props.onDragMove === 'function') { 13 | return props.onDragMove(newValue, from, to); 14 | } 15 | } 16 | return ( 17 |
18 | {container.map((item, index)=>{ 19 | if(React.isValidElement(item)){ 20 | return React.cloneElement(item, { 21 | draggable, 22 | //开始拖动元素时触发此事件 23 | onDragStart(){ 24 | curDragIndex = index; 25 | }, 26 | /* 27 | * 当被拖动的对象进入其容器范围内时触发此事件 28 | * 在自身拖动时也会触发该事件 29 | */ 30 | onDragEnter() { 31 | onChange(curDragIndex, index); 32 | curDragIndex = index; 33 | }, 34 | /* 35 | * 当被拖动的对象在另一对象容器范围内拖动时触发此事件 36 | * 在拖动元素时,每隔350毫秒会触发onDragOver事件 37 | */ 38 | onDragOver(e) { 39 | /* 40 | * 默认情况下,数据/元素不能放置到其他元素中。如果要实现该功能,我们需要 41 | * 防止元素的默认处理方法,我们可以通过调用event.preventDefault()方法来实现onDragOver事件 42 | */ 43 | e.preventDefault(); 44 | }, 45 | //完成元素拖动后触发 46 | onDragEnd(){ 47 | curDragIndex = null; 48 | if(typeof props.onDragEnd === 'function'){ 49 | props.onDragEnd(index); 50 | }; 51 | }, 52 | }) 53 | } 54 | return item; 55 | })} 56 |
57 | ); 58 | } 59 | 60 | function arrMove(arr, fromIndex, toIndex) { 61 | if (fromIndex !== toIndex) { 62 | arr = arr.concat(); 63 | let item = arr.splice(fromIndex, 1)[0]; 64 | arr.splice(toIndex, 0, item); 65 | }; 66 | return arr; 67 | } -------------------------------------------------------------------------------- /libs/DragSort/example.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DragSort from './index.js'; 3 | 4 | export default class DragSortExample extends React.Component { 5 | constructor(props) { 6 | super(props); 7 | this.state = { 8 | list: [{ 9 | name: 'title' 10 | }, { 11 | name: 'name' 12 | }, { 13 | name: 'code' 14 | }, { 15 | name: 'email' 16 | }], 17 | curMoveItem: null, 18 | index: '', 19 | dragged: false, 20 | } 21 | } 22 | 23 | handleDragMove = (data, from, to) => { 24 | this.setState({ 25 | curMoveItem: to, 26 | list: data, 27 | index: null, 28 | }); 29 | } 30 | 31 | handleDragEnd = (index) => { 32 | this.setState({ 33 | curMoveItem: null, 34 | dragged: false, 35 | index, 36 | }); 37 | } 38 | 39 | enter = (index) => { 40 | if (this.state.index !== null) { 41 | this.setState({ 42 | index, 43 | }); 44 | }; 45 | } 46 | 47 | leave = () => { 48 | if (this.state.index !== null) { 49 | this.setState({ 50 | index: '', 51 | }); 52 | }; 53 | } 54 | 55 | render() { 56 | const { 57 | dragged, 58 | } = this.state; 59 | const el = this.state.list.map((item, index) => { 60 | return ( 61 |
69 |
{item.name}
70 |
71 | ); 72 | }); 73 | return ( 74 |
75 | 84 |
85 | ); 86 | } 87 | } -------------------------------------------------------------------------------- /libs/Input/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './index.less' 3 | 4 | class Input extends React.PureComponent { 5 | static defaultProps = { 6 | disabled: false, 7 | type: 'text', 8 | } 9 | 10 | handleChange = (e) => { 11 | const { 12 | onChange, 13 | index, 14 | } = this.props; 15 | if (onChange) { 16 | onChange(e, index); 17 | }; 18 | } 19 | 20 | handleBlur = (e) => { 21 | const { 22 | onBlur, 23 | index, 24 | } = this.props; 25 | if (onBlur) { 26 | onBlur(e, index); 27 | }; 28 | } 29 | 30 | fixControlledValue = (value) => { 31 | if (typeof value === 'undefined' || value === null) { 32 | return ''; 33 | }; 34 | return value; 35 | } 36 | 37 | render() { 38 | const { 39 | type, 40 | name, 41 | width, 42 | margin, 43 | style, 44 | maxLength, 45 | rows, 46 | disabled, 47 | ...otherProps 48 | } = this.props; 49 | /* 50 | * defaultValue只会在第一次渲染有效 51 | * defaultValue和value尽量不共存,如果共存的话value将会覆盖defaultValue 52 | * 在共存的情况下,如果value值为undefined或者null,会被defaultValue覆盖 53 | */ 54 | if ('value' in otherProps) { 55 | otherProps.value = this.fixControlledValue(otherProps.value); 56 | delete otherProps.defaultValue; 57 | }; 58 | return ( 59 |
62 | {type === 'textarea' ? ( 63 |