diff --git a/CHANGELOG.md b/CHANGELOG.md index e7fa27f..9693a7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +### 0.3.2 + +- [!] 列表支持`ui:readonly`进入只读模式,不允许对列表进行增、删和拖拽操作 +- [!] fix 了日期类组件传入数据变化后显示日期无变化的 bug + ### 0.3.1 - [+] 重磅:schema 里大部分属性现在都支持函数表达式,方便表单组件间的关联(详见文档 UISchema、PropsSchema 部分) diff --git a/docs/demo/index.html b/docs/demo/index.html index 28cc5da..83fdd39 100644 --- a/docs/demo/index.html +++ b/docs/demo/index.html @@ -10,9 +10,9 @@
- + - + diff --git a/docs/ui-schema.md b/docs/ui-schema.md index d6ffe0b..bed0fdc 100644 --- a/docs/ui-schema.md +++ b/docs/ui-schema.md @@ -63,7 +63,14 @@ ### 控制表单项的 UI 展示(共通配置) - `ui:disabled`: 可控制 input、number、date、checkbox、radio、select、switch 对于组件的 disabled 属性(变灰不可点击) -- `ui:readonly`:可控制 input、number 组件中的 readonly 属性(不可编辑,但不变灰) +- `ui:readonly`:可控制 input、number 组件中的 readonly 属性(不可编辑,但不变灰),列表也支持`readonly`,效果是列表的控件都会隐藏,导致列表不能增、删和拖拽,进入“只读”模式。但注意列表内的内容还是允许修改的,所以特别要注意如果列表套列表的场景,内部的列表也要 "ui:readonly": true + +```js +"someList": { + "ui:readonly": true +} +``` + - `ui:hidden`:可控制所有基础组件是否显示,可使用 true/false 或表达式,例如: ```json diff --git a/package.json b/package.json index dfbd947..3d3bee9 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "form-render", - "version": "0.3.1", + "version": "0.3.2", "description": "通过 JSON Schema 生成标准 Form,常用于自定义搭建配置界面生成", "repository": { "type": "git", diff --git a/src/base/resolve.js b/src/base/resolve.js index eed714f..9651dd7 100644 --- a/src/base/resolve.js +++ b/src/base/resolve.js @@ -9,21 +9,7 @@ function clone(data) { // 获取当前字段默认值 function getDefaultValue({ default: def, enum: enums = [], type }) { - // 如果设置默认值,优先从默认值中获取 - if (typeof def !== 'undefined') { - return def; - } - // array且enum的情况,为多选框,默认值[] - if (type === 'array' && enums.length > 0) { - return []; - } - // 如果enum是表达式,不处理 - // 如果设置枚举值,其次从枚举值中获取 - if (Array.isArray(enums) && enums[0] && typeof enums[0] !== 'undefined') { - return enums[0]; - } - // 最后使用对应基础类型的默认值 - return { + const defaultValue = { array: [], boolean: false, integer: '', @@ -32,7 +18,45 @@ function getDefaultValue({ default: def, enum: enums = [], type }) { object: {}, string: '', range: null, - }[type]; + }; + + const isFunction = func => { + if (typeof func === 'function') { + return true; + } + if (typeof func === 'string' && func.substring(0, 1) === '@') { + return true; + } + return false; + }; + + if (isFunction(def)) { + return defaultValue[type]; + } + if (isFunction(enums)) { + if (type === 'array') { + return []; + } + if (type === 'string' || type === 'number') { + return ''; + } + } + + // 如果设置默认值,优先从默认值中获取 + if (typeof def !== 'undefined') { + return def; + } + // array且enum的情况,为多选框,默认值[] + if (type === 'array' && enums.length) { + return []; + } + // 如果enum是表达式,不处理 + // 如果设置枚举值,其次从枚举值中获取 + if (Array.isArray(enums) && enums[0] && typeof enums[0] !== 'undefined') { + return enums[0]; + } + // 最后使用对应基础类型的默认值 + return defaultValue[type]; } function resolve(schema, data, options = {}) { @@ -44,6 +68,7 @@ function resolve(schema, data, options = {}) { // 数组子集 items, // 必选值,对象的子集 + default: def, required = [], } = schema; const { @@ -66,6 +91,9 @@ function resolve(schema, data, options = {}) { return ret; } if (type === 'array') { + if (def) { + return value; + } const subs = [].concat(items || []); const ret = []; value.forEach && diff --git a/src/widgets/antd/date.jsx b/src/widgets/antd/date.jsx index 6d642d3..56c8be1 100644 --- a/src/widgets/antd/date.jsx +++ b/src/widgets/antd/date.jsx @@ -19,7 +19,7 @@ export default function date(p) { let defaultObj = {}; if (p.value) { defaultObj = { - defaultValue: moment(p.value, dateFormat), + value: moment(p.value, dateFormat), }; } diff --git a/src/widgets/antd/list.jsx b/src/widgets/antd/list.jsx index 9a0b2d9..855b262 100644 --- a/src/widgets/antd/list.jsx +++ b/src/widgets/antd/list.jsx @@ -51,7 +51,7 @@ class ListItem extends React.Component { render() { const { item, p = {}, name, fold } = this.props; const descProps = { ...p, index: name }; - const { options = {} } = p; + const { options = {}, readonly } = p; const { foldable: canFold, hideDelete } = options; // 只有当items为object时才做收起(fold)处理 const isObj = p.schema.items && p.schema.items.type == 'object'; @@ -72,8 +72,8 @@ class ListItem extends React.Component { style={{ position: 'absolute', top: 12, right: 36 }} /> )} - - {!((canFold && fold) || hideDelete) && ( + {!readonly && } + {!((canFold && fold) || hideDelete || readonly) && ( - {p.extraButtons && - p.extraButtons.length > 0 && - p.extraButtons.map(item => ( - - ))} - + {!readonly && ( +
+ + {p.extraButtons && + p.extraButtons.length > 0 && + p.extraButtons.map(item => ( + + ))} +
+ )} ); } diff --git a/src/widgets/fusion/date.jsx b/src/widgets/fusion/date.jsx index 3d4227d..071637d 100644 --- a/src/widgets/fusion/date.jsx +++ b/src/widgets/fusion/date.jsx @@ -19,7 +19,7 @@ export default function date(p) { let defaultObj = {}; if (p.value) { defaultObj = { - defaultValue: moment(p.value, dateFormat), + value: moment(p.value, dateFormat), }; } diff --git a/src/widgets/fusion/list.jsx b/src/widgets/fusion/list.jsx index 10352ed..9310a43 100644 --- a/src/widgets/fusion/list.jsx +++ b/src/widgets/fusion/list.jsx @@ -48,7 +48,7 @@ class ListItem extends React.Component { render() { const { item, p = {}, name, fold } = this.props; const descProps = { ...p, index: name }; - const { options = {} } = p; + const { options = {}, readonly } = p; const { foldable: canFold, hideDelete } = options; // 只有当items为object时才做收起(fold)处理 const isObj = p.schema.items && p.schema.items.type == 'object'; @@ -69,8 +69,8 @@ class ListItem extends React.Component { style={{ position: 'absolute', top: 12, right: 36 }} /> )} - - {!((canFold && fold) || hideDelete) && ( + {!readonly && } + {!((canFold && fold) || hideDelete || readonly) && ( - {p.extraButtons && - p.extraButtons.length > 0 && - p.extraButtons.map(item => ( - - ))} - + {!readonly && ( +
+ + {p.extraButtons && + p.extraButtons.length > 0 && + p.extraButtons.map(item => ( + + ))} +
+ )} ); } diff --git a/webpack.config.js b/webpack.config.js index 1e61df8..459977c 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,7 +1,7 @@ const { resolve } = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); -const UglifyJsPlugin = require('uglifyjs-webpack-plugin') +const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); module.exports = { @@ -38,27 +38,24 @@ module.exports = { }, { test: /\.css$/, - use: [ - 'style-loader', - 'css-loader' - ], + use: ['style-loader', 'css-loader'], }, ], }, plugins: [ new MonacoWebpackPlugin({ languages: ['json'], - features: ['snippets', 'suggest'] + features: ['snippets', 'suggest'], }), new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }), new HtmlWebpackPlugin({ resources: { js: [ - 'react@16.x/umd/react.production.min.js', - 'react-dom@16.x/umd/react-dom.production.min.js', + 'react@16.x/umd/react.development.js', + 'react-dom@16.x/umd/react-dom.development.js', 'prop-types@15.x/prop-types.min.js', 'moment@2.24.0/min/moment.min.js', - '@alifd/next@1.x/dist/next.min.js' + '@alifd/next@1.x/dist/next.min.js', ], css: ['@alifd/next@1.x/dist/next.min.css'], }, @@ -73,14 +70,14 @@ module.exports = { uglifyOptions: { compress: { unused: true, - drop_debugger: true + drop_debugger: true, }, warnings: false, output: { - comments: false - } - } - }) + comments: false, + }, + }, + }), ], externals: { react: 'var window.React', @@ -101,7 +98,7 @@ module.exports = { resolve: { extensions: ['.js', '.jsx'], alias: { - 'monaco-editor': 'monaco-editor/esm/vs/editor/editor.api' - } + 'monaco-editor': 'monaco-editor/esm/vs/editor/editor.api', + }, }, };