Merge pull request #331 from 2betop/master

tabWidth 改成 2 因为 4 的时候 prettier 处理不正确
This commit is contained in:
liaoxuezhi 2019-11-07 10:43:44 +08:00 committed by GitHub
commit bd5b6dd840
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
258 changed files with 60897 additions and 55769 deletions

View File

@ -8,7 +8,7 @@ insert_final_newline = true
[**.{js,ts,tsx,scss}]
indent_style = space
indent_size = 4
indent_size = 2
[*.md]
trim_trailing_whitespace = false
trim_trailing_whitespace = false

View File

@ -1,11 +1,12 @@
{
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"singleQuote": true,
"semi": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"jsxBracketSameLine": false
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"semi": true,
"trailingComma": "none",
"bracketSpacing": false,
"quoteProps": "consistent",
"arrowParens": "avoid",
"jsxBracketSameLine": false
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,40 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "音频播放器",
"body": [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '音频播放器',
body: [
{
type: 'audio',
autoPlay: false,
rates: [1.0, 1.5, 2.0],
src:
'https://amis.bj.bcebos.com/amis/2019-7/1562137295708/chicane-poppiholla-original-radio-edit%20(1).mp3'
},
{
type: 'form',
title: '',
actions: [],
className: 'b v-middle inline w-lg h-xs',
controls: [
{
"type": "audio",
"autoPlay": false,
"rates": [1.0, 1.5, 2.0],
"src": "https://amis.bj.bcebos.com/amis/2019-7/1562137295708/chicane-poppiholla-original-radio-edit%20(1).mp3",
type: 'card',
className: 'v-middle w inline no-border',
header: {
title: '歌曲名称',
subTitle: '专辑名称',
description: 'description',
avatarClassName: 'pull-left thumb-md avatar m-r no-border',
avatar:
'http://hiphotos.baidu.com/fex/%70%69%63/item/c9fcc3cec3fdfc03ccabb38edd3f8794a4c22630.jpg'
}
},
{
"type": 'form',
"title": '',
"actions": [],
"className": 'b v-middle inline w-lg h-xs',
"controls": [
{
"type": "card",
"className": 'v-middle w inline no-border',
"header": {
"title": "歌曲名称",
"subTitle": "专辑名称",
"description": "description",
"avatarClassName": "pull-left thumb-md avatar m-r no-border",
"avatar": "http://hiphotos.baidu.com/fex/%70%69%63/item/c9fcc3cec3fdfc03ccabb38edd3f8794a4c22630.jpg"
}
},
{
"type": "audio",
"className": 'v-middle no-border',
"src": "https://amis.bj.bcebos.com/amis/2019-7/1562137295708/chicane-poppiholla-original-radio-edit%20(1).mp3",
"controls": ['play']
}
]
type: 'audio',
className: 'v-middle no-border',
src:
'https://amis.bj.bcebos.com/amis/2019-7/1562137295708/chicane-poppiholla-original-radio-edit%20(1).mp3',
controls: ['play']
}
]
}
]
}
]
};

View File

@ -1,332 +1,332 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "带边栏联动",
aside: {
type: 'form',
wrapWithPanel: false,
target: 'window', // location
controls: [
{
type: 'tree',
name: 'cat',
inputClassName: 'no-border',
submitOnChange: true,
options: [
{
label: '分类1',
value: 'cat1'
},
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '带边栏联动',
aside: {
type: 'form',
wrapWithPanel: false,
target: 'window', // location
controls: [
{
type: 'tree',
name: 'cat',
inputClassName: 'no-border',
submitOnChange: true,
options: [
{
label: '分类1',
value: 'cat1'
},
{
label: '分类2',
value: 'cat2'
},
{
label: '分类2',
value: 'cat2'
},
{
label: '分类3',
value: 'cat3'
},
{
label: '分类3',
value: 'cat3'
},
{
label: '分类4',
value: 'cat4'
}
]
}
{
label: '分类4',
value: 'cat4'
}
]
},
toolbar: [
{
type: "button",
actionType: "dialog",
label: "新增",
primary: true,
dialog: {
title: "新增",
body: {
type: "form",
name: "sample-edit-form",
api: "post:/api/sample",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "text",
name: "grade",
label: "CSS grade"
}
]
}
}
]
},
toolbar: [
{
type: 'button',
actionType: 'dialog',
label: '新增',
primary: true,
dialog: {
title: '新增',
body: {
type: 'form',
name: 'sample-edit-form',
api: 'post:/api/sample',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
],
body: {
type: "crud",
draggable: true,
api: "/api/sample",
filter: {
title: "条件搜索",
submitText: "",
controls: [
{
type: "text",
name: "keywords",
placeholder: "通过关键字搜索",
addOn: {
label: "搜索",
type: "submit"
}
},
{
type: "plain",
text: "这里的表单项可以配置多个"
}
]
},
bulkActions: [
{
label: "批量删除",
actionType: "ajax",
api: "delete:/api/sample/$ids",
confirmText: "确定要批量删除?"
},
{
label: "批量修改",
actionType: "dialog",
dialog: {
title: "批量编辑",
name: "sample-bulk-edit",
body: {
type: "form",
api: "/api/sample/bulkUpdate2",
controls: [
{
type: 'hidden',
name: 'ids'
},
{
type: "text",
name: "engine",
label: "Engine"
}
]
}
}
}
],
quickSaveApi: "/api/sample/bulkUpdate",
quickSaveItemApi: "/api/sample/$id",
columns: [
{
name: "id",
label: "ID",
width: 20,
sortable: true,
type: "text",
toggled: true
},
{
name: "engine",
label: "Rendering engine",
sortable: true,
searchable: true,
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: true
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
quickEdit: true,
type: "text",
toggled: true
},
{
name: "grade",
label: "CSS grade",
quickEdit: {
mode: "inline",
type: "select",
options: ["A", "B", "C", "D", "X"],
saveImmediately: true
},
type: "text",
toggled: true
},
{
type: "operation",
label: "操作",
width: 130,
buttons: [
{
type: "button",
icon: "fa fa-eye",
actionType: "dialog",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
icon: "fa fa-pencil",
actionType: "dialog",
dialog: {
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "text",
name: "grade",
label: "CSS grade"
}
]
}
}
},
{
type: "button",
icon: "fa fa-times text-danger",
actionType: "ajax",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
toggled: true
}
]
}
}
],
body: {
type: 'crud',
draggable: true,
api: '/api/sample',
filter: {
title: '条件搜索',
submitText: '',
controls: [
{
type: 'text',
name: 'keywords',
placeholder: '通过关键字搜索',
addOn: {
label: '搜索',
type: 'submit'
}
},
{
type: 'plain',
text: '这里的表单项可以配置多个'
}
]
},
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: 'delete:/api/sample/$ids',
confirmText: '确定要批量删除?'
},
{
label: '批量修改',
actionType: 'dialog',
dialog: {
title: '批量编辑',
name: 'sample-bulk-edit',
body: {
type: 'form',
api: '/api/sample/bulkUpdate2',
controls: [
{
type: 'hidden',
name: 'ids'
},
{
type: 'text',
name: 'engine',
label: 'Engine'
}
]
}
}
}
],
quickSaveApi: '/api/sample/bulkUpdate',
quickSaveItemApi: '/api/sample/$id',
columns: [
{
name: 'id',
label: 'ID',
width: 20,
sortable: true,
type: 'text',
toggled: true
},
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
searchable: true,
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true
},
{
name: 'grade',
label: 'CSS grade',
quickEdit: {
mode: 'inline',
type: 'select',
options: ['A', 'B', 'C', 'D', 'X'],
saveImmediately: true
},
type: 'text',
toggled: true
},
{
type: 'operation',
label: '操作',
width: 130,
buttons: [
{
type: 'button',
icon: 'fa fa-eye',
actionType: 'dialog',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-pencil',
actionType: 'dialog',
dialog: {
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-times text-danger',
actionType: 'ajax',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
toggled: true
}
]
}
};

View File

@ -1,91 +1,91 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "增删改查列类型汇总",
body: {
type: "crud",
api: "/api/mock2/crud/list",
columns: [
{
name: "id",
label: "ID",
type: "text"
},
{
name: "audio",
label: "音频",
type: "audio"
},
{
name: "carousel",
label: "轮播图",
type: "carousel",
width: "300"
},
{
name: "text",
label: "文本",
type: "text"
},
{
type: 'image',
label: '图片',
name: 'image',
popOver: {
title: '查看大图',
body: '<div class="w-xxl"><img class="w-full" src="${image}"/></div>'
}
},
{
name: 'date',
type: 'date',
label: '日期'
},
{
name: "progress",
label: "进度",
type: "progress"
},
{
name: "boolean",
label: "状态",
type: "status"
},
{
name: "boolean",
label: "开关",
type: "switch",
// readOnly: false //
},
{
name: "type",
label: "映射",
type: "mapping",
map: {
"*": "其他:${type}",
"1": "<span class='label label-info'>漂亮</span>",
"2": "<span class='label label-success'>开心</span>",
"3": "<span class='label label-danger'>惊吓</span>",
"4": "<span class='label label-warning'>紧张</span>"
}
},
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '增删改查列类型汇总',
body: {
type: 'crud',
api: '/api/mock2/crud/list',
columns: [
{
name: 'id',
label: 'ID',
type: 'text'
},
{
name: 'audio',
label: '音频',
type: 'audio'
},
{
name: 'carousel',
label: '轮播图',
type: 'carousel',
width: '300'
},
{
name: 'text',
label: '文本',
type: 'text'
},
{
type: 'image',
label: '图片',
name: 'image',
popOver: {
title: '查看大图',
body: '<div class="w-xxl"><img class="w-full" src="${image}"/></div>'
}
},
{
name: 'date',
type: 'date',
label: '日期'
},
{
name: 'progress',
label: '进度',
type: 'progress'
},
{
name: 'boolean',
label: '状态',
type: 'status'
},
{
name: 'boolean',
label: '开关',
type: 'switch'
// readOnly: false //
},
{
name: 'type',
label: '映射',
type: 'mapping',
map: {
'*': '其他:${type}',
'1': "<span class='label label-info'>漂亮</span>",
'2': "<span class='label label-success'>开心</span>",
'3': "<span class='label label-danger'>惊吓</span>",
'4': "<span class='label label-warning'>紧张</span>"
}
},
{
name: 'list',
type: 'list',
label: 'List',
placeholder: '-',
size: "sm",
listItem: {
title: '${title}',
subTitle: '${description}'
}
},
{
name: 'list',
type: 'list',
label: 'List',
placeholder: '-',
size: 'sm',
listItem: {
title: '${title}',
subTitle: '${description}'
}
},
{
name: 'json',
type: 'json',
label: 'Json'
}
]
}
{
name: 'json',
type: 'json',
label: 'Json'
}
]
}
};

View File

@ -1,301 +1,301 @@
const table = {
type: "table",
data: [
{
engine: "Other browsers",
browser: "All others",
platform: "-",
version: "-",
grade: "U",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 56,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Misc",
browser: "PSP browser",
platform: "PSP",
version: "-",
grade: "C",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 55,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Misc",
browser: "PSP browser",
platform: "PSP",
version: "-",
grade: "C",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 55,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Other browsers",
browser: "All others",
platform: "-",
version: "-",
grade: "U",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 56,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Misc",
browser: "PSP browser",
platform: "PSP",
version: "-",
grade: "C",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 55,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Misc",
browser: "PSP browser",
platform: "PSP",
version: "-",
grade: "C",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 55,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Other browsers",
browser: "All others",
platform: "-",
version: "-",
grade: "U",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 56,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Misc",
browser: "PSP browser",
platform: "PSP",
version: "-",
grade: "C",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 55,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Misc",
browser: "PSP browser",
platform: "PSP",
version: "-",
grade: "C",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 55,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
},
{
engine: "Other browsers",
browser: "All others",
platform: "-",
version: "-",
grade: "U",
progress: 50,
status: true,
image:
"http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg",
weight: 56,
others: null,
createdAt: "2017-11-17T08:47:50.000Z",
updatedAt: "2017-11-17T08:47:50.000Z"
}
].map((item, key) => ({
...item,
id: key + 1
})),
columns: [
{
name: "id",
label: "ID",
width: 20,
sortable: true,
type: "text",
toggled: true,
fixed: 'left'
},
{
name: "engine",
label: "Rendering engine",
sortable: true,
searchable: true,
type: "text",
toggled: true,
fixed: 'left'
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: true
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
quickEdit: true,
type: "text",
toggled: true
},
{
name: "grade",
label: "CSS grade",
quickEdit: {
mode: "inline",
type: "select",
options: ["A", "B", "C", "D", "X"],
saveImmediately: true
},
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: true
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
quickEdit: true,
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: true
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
quickEdit: true,
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: true
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true,
fixed: 'right'
},
{
name: "version",
label: "Engine version",
quickEdit: true,
type: "text",
toggled: true,
fixed: 'right'
},
]
type: 'table',
data: [
{
engine: 'Other browsers',
browser: 'All others',
platform: '-',
version: '-',
grade: 'U',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 56,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Misc',
browser: 'PSP browser',
platform: 'PSP',
version: '-',
grade: 'C',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 55,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Misc',
browser: 'PSP browser',
platform: 'PSP',
version: '-',
grade: 'C',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 55,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Other browsers',
browser: 'All others',
platform: '-',
version: '-',
grade: 'U',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 56,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Misc',
browser: 'PSP browser',
platform: 'PSP',
version: '-',
grade: 'C',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 55,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Misc',
browser: 'PSP browser',
platform: 'PSP',
version: '-',
grade: 'C',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 55,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Other browsers',
browser: 'All others',
platform: '-',
version: '-',
grade: 'U',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 56,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Misc',
browser: 'PSP browser',
platform: 'PSP',
version: '-',
grade: 'C',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 55,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Misc',
browser: 'PSP browser',
platform: 'PSP',
version: '-',
grade: 'C',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 55,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
},
{
engine: 'Other browsers',
browser: 'All others',
platform: '-',
version: '-',
grade: 'U',
progress: 50,
status: true,
image:
'http://hiphotos.baidu.com/fex/%70%69%63/item/0d338744ebf81a4cff2f4cd6de2a6059252da694.jpg',
weight: 56,
others: null,
createdAt: '2017-11-17T08:47:50.000Z',
updatedAt: '2017-11-17T08:47:50.000Z'
}
].map((item, key) => ({
...item,
id: key + 1
})),
columns: [
{
name: 'id',
label: 'ID',
width: 20,
sortable: true,
type: 'text',
toggled: true,
fixed: 'left'
},
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
searchable: true,
type: 'text',
toggled: true,
fixed: 'left'
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true
},
{
name: 'grade',
label: 'CSS grade',
quickEdit: {
mode: 'inline',
type: 'select',
options: ['A', 'B', 'C', 'D', 'X'],
saveImmediately: true
},
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true,
fixed: 'right'
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true,
fixed: 'right'
}
]
};
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "固顶和列固定示例",
remark: "bla bla bla",
body: [
table,
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
table
]
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '固顶和列固定示例',
remark: 'bla bla bla',
body: [
table,
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
'<div>分割</div>',
table
]
};

View File

@ -1,198 +1,198 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "开启单条底部展示功能",
body: {
type: "crud",
draggable: true,
api: "/api/sample",
footable: {
expand: 'first',
accordion: true
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '开启单条底部展示功能',
body: {
type: 'crud',
draggable: true,
api: '/api/sample',
footable: {
expand: 'first',
accordion: true
},
columns: [
{
name: 'id',
label: 'ID',
width: 20,
sortable: true,
type: 'text',
toggled: true
},
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
searchable: true,
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true
},
{
name: 'grade',
label: 'CSS grade',
breakpoint: '*',
quickEdit: {
mode: 'inline',
type: 'select',
options: ['A', 'B', 'C', 'D', 'X'],
inputClassName: 'w-xs',
saveImmediately: true
},
columns: [
{
name: "id",
label: "ID",
width: 20,
sortable: true,
type: "text",
toggled: true
},
{
name: "engine",
label: "Rendering engine",
sortable: true,
searchable: true,
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: true
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
quickEdit: true,
type: "text",
toggled: true
},
{
name: "grade",
label: "CSS grade",
breakpoint: '*',
quickEdit: {
mode: "inline",
type: "select",
options: ["A", "B", "C", "D", "X"],
inputClassName: 'w-xs',
saveImmediately: true
},
type: "text",
toggled: true
},
{
type: "operation",
label: "操作",
width: 100,
breakpoint: '*',
buttons: [
{
type: "button",
icon: "fa fa-eye",
actionType: "dialog",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
icon: "fa fa-pencil",
actionType: "drawer",
drawer: {
position: 'left',
size: 'lg',
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "select",
name: "grade",
label: "CSS grade",
options: ["A", "B", "C", "D", "X"],
}
]
}
}
},
{
type: "button",
icon: "fa fa-times text-danger",
actionType: "ajax",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
toggled: true
type: 'text',
toggled: true
},
{
type: 'operation',
label: '操作',
width: 100,
breakpoint: '*',
buttons: [
{
type: 'button',
icon: 'fa fa-eye',
actionType: 'dialog',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
]
}
},
{
type: 'button',
icon: 'fa fa-pencil',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'lg',
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'select',
name: 'grade',
label: 'CSS grade',
options: ['A', 'B', 'C', 'D', 'X']
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-times text-danger',
actionType: 'ajax',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
toggled: true
}
]
}
};

View File

@ -1,221 +1,221 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "增删改查示例",
remark: "bla bla bla",
body: {
type: "crud",
api: "/api/sample",
// api: "/api/mock2/crud/table?waitSeconds=100000",
mode: "cards",
defaultParams: {
perPage: 12,
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '增删改查示例',
remark: 'bla bla bla',
body: {
type: 'crud',
api: '/api/sample',
// api: "/api/mock2/crud/table?waitSeconds=100000",
mode: 'cards',
defaultParams: {
perPage: 12
},
// fixAlignment: true,
// masonryLayout: true,
filter: {
title: '条件搜索',
submitText: '',
controls: [
{
type: 'text',
name: 'keywords',
placeholder: '通过关键字搜索',
addOn: {
label: '搜索',
type: 'submit'
}
},
// fixAlignment: true,
// masonryLayout: true,
filter: {
title: "条件搜索",
submitText: "",
controls: [
{
type: "text",
name: "keywords",
placeholder: "通过关键字搜索",
addOn: {
label: "搜索",
type: "submit"
}
},
{
type: "plain",
text: "这只是个示例, 目前搜索对查询结果无效."
}
]
},
bulkActions: [
{
label: "批量删除",
actionType: "ajax",
api: "delete:/api/sample/${ids|raw}",
confirmText: "确定要批量删除?"
},
{
label: "批量修改",
actionType: "dialog",
dialog: {
title: "批量编辑",
name: "sample-bulk-edit",
body: {
type: "form",
api: "/api/sample/bulkUpdate2",
controls: [
{
type: "hidden",
name: "ids"
},
{
type: "text",
name: "engine",
label: "Engine"
}
]
}
}
}
],
quickSaveApi: "/api/sample/bulkUpdate",
quickSaveItemApi: "/api/sample/$id",
draggable: true,
card: {
header: {
title: "$engine",
subTitle: "$platform",
subTitlePlaceholder: "暂无说明",
avatar:
'<%= data.avatar || "http://bos.nj.bpc.baidu.com/showx/146bc2ce1b30f3824838f4208ad2663c" %>',
avatarClassName: "pull-left thumb b-3x m-r"
},
actions: [
{
type: "button",
label: "查看",
actionType: "dialog",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
label: "编辑",
actionType: "dialog",
dialog: {
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "text",
name: "grade",
label: "CSS grade"
}
]
}
}
},
{
type: "button",
label: "删除",
actionType: "ajax",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
body: [
{
name: "engine",
label: "engine",
sortable: true,
quickEdit: true
},
{
name: "browser",
label: "Browser"
},
{
name: "platform",
label: "Platform"
},
{
name: "version",
label: "version"
}
]
{
type: 'plain',
text: '这只是个示例, 目前搜索对查询结果无效.'
}
]
},
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: 'delete:/api/sample/${ids|raw}',
confirmText: '确定要批量删除?'
},
{
label: '批量修改',
actionType: 'dialog',
dialog: {
title: '批量编辑',
name: 'sample-bulk-edit',
body: {
type: 'form',
api: '/api/sample/bulkUpdate2',
controls: [
{
type: 'hidden',
name: 'ids'
},
{
type: 'text',
name: 'engine',
label: 'Engine'
}
]
}
}
}
],
quickSaveApi: '/api/sample/bulkUpdate',
quickSaveItemApi: '/api/sample/$id',
draggable: true,
card: {
header: {
title: '$engine',
subTitle: '$platform',
subTitlePlaceholder: '暂无说明',
avatar:
'<%= data.avatar || "http://bos.nj.bpc.baidu.com/showx/146bc2ce1b30f3824838f4208ad2663c" %>',
avatarClassName: 'pull-left thumb b-3x m-r'
},
actions: [
{
type: 'button',
label: '查看',
actionType: 'dialog',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
},
{
type: 'button',
label: '编辑',
actionType: 'dialog',
dialog: {
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
}
},
{
type: 'button',
label: '删除',
actionType: 'ajax',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
body: [
{
name: 'engine',
label: 'engine',
sortable: true,
quickEdit: true
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'platform',
label: 'Platform'
},
{
name: 'version',
label: 'version'
}
]
}
}
};

View File

@ -1,107 +1,107 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "支持表头分组,通过在 cloumn 上设置 groupName 实现。",
body: {
type: "table",
data: {
items: [
{
"engine": "Trident",
"browser": "Internet Explorer 4.2",
"platform": "Win 95+",
"version": "4",
"grade": "A"
},
{
"engine": "Trident",
"browser": "Internet Explorer 4.2",
"platform": "Win 95+",
"version": "4",
"grade": "B"
},
{
"engine": "Trident",
"browser": "AOL browser (AOL desktop)",
"platform": "Win 95+",
"version": "4",
"grade": "C"
},
{
"engine": "Trident",
"browser": "AOL browser (AOL desktop)",
"platform": "Win 98",
"version": "3",
"grade": "A"
},
{
"engine": "Trident",
"browser": "AOL browser (AOL desktop)",
"platform": "Win 98",
"version": "4",
"grade": "A"
},
{
"engine": "Gecko",
"browser": "Firefox 1.0",
"platform": "Win 98+ / OSX.2+",
"version": "4",
"grade": "A"
},
{
"engine": "Gecko",
"browser": "Firefox 1.0",
"platform": "Win 98+ / OSX.2+",
"version": "5",
"grade": "A"
},
{
"engine": "Gecko",
"browser": "Firefox 2.0",
"platform": "Win 98+ / OSX.2+",
"version": "5",
"grade": "B"
},
{
"engine": "Gecko",
"browser": "Firefox 2.0",
"platform": "Win 98+ / OSX.2+",
"version": "5",
"grade": "C"
},
{
"engine": "Gecko",
"browser": "Firefox 2.0",
"platform": "Win 98+ / OSX.2+",
"version": "5",
"grade": "D"
}
]
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '支持表头分组,通过在 cloumn 上设置 groupName 实现。',
body: {
type: 'table',
data: {
items: [
{
engine: 'Trident',
browser: 'Internet Explorer 4.2',
platform: 'Win 95+',
version: '4',
grade: 'A'
},
columns: [
{
name: "engine",
label: "Rendering engine",
groupName: "A"
},
{
name: "browser",
label: "Browser",
groupName: "A"
},
{
name: "platform",
label: "Platform(s)",
groupName: "B"
},
{
name: "version",
label: "Engine version",
groupName: "B"
},
{
name: "grade",
label: "CSS grade",
}
]
}
{
engine: 'Trident',
browser: 'Internet Explorer 4.2',
platform: 'Win 95+',
version: '4',
grade: 'B'
},
{
engine: 'Trident',
browser: 'AOL browser (AOL desktop)',
platform: 'Win 95+',
version: '4',
grade: 'C'
},
{
engine: 'Trident',
browser: 'AOL browser (AOL desktop)',
platform: 'Win 98',
version: '3',
grade: 'A'
},
{
engine: 'Trident',
browser: 'AOL browser (AOL desktop)',
platform: 'Win 98',
version: '4',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Firefox 1.0',
platform: 'Win 98+ / OSX.2+',
version: '4',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Firefox 1.0',
platform: 'Win 98+ / OSX.2+',
version: '5',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Firefox 2.0',
platform: 'Win 98+ / OSX.2+',
version: '5',
grade: 'B'
},
{
engine: 'Gecko',
browser: 'Firefox 2.0',
platform: 'Win 98+ / OSX.2+',
version: '5',
grade: 'C'
},
{
engine: 'Gecko',
browser: 'Firefox 2.0',
platform: 'Win 98+ / OSX.2+',
version: '5',
grade: 'D'
}
]
},
columns: [
{
name: 'engine',
label: 'Rendering engine',
groupName: 'A'
},
{
name: 'browser',
label: 'Browser',
groupName: 'A'
},
{
name: 'platform',
label: 'Platform(s)',
groupName: 'B'
},
{
name: 'version',
label: 'Engine version',
groupName: 'B'
},
{
name: 'grade',
label: 'CSS grade'
}
]
}
};

View File

@ -1,223 +1,228 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "增删改查示例",
remark: "bla bla bla",
body: {
type: "crud",
api: "/api/sample",
headerToolbar: ['bulkActions', {
type: 'columns-toggler',
className: 'pull-right',
align: 'right'
}, {
type: 'drag-toggler',
className: 'pull-right'
}, {
type: 'pagination',
className: 'pull-right'
}],
itemActions: [
{
type: "button",
label: "查看",
actionType: "dialog",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
label: "编辑",
actionType: "drawer",
drawer: {
position: 'left',
size: 'lg',
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "select",
name: "grade",
label: "CSS grade",
options: ["A", "B", "C", "D", "X"],
}
]
}
}
},
{
type: "button",
label: "删除",
actionType: "ajax",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
bulkActions: [
{
label: "批量删除",
actionType: "ajax",
api: "delete:/api/sample/${ids|raw}",
confirmText: "确定要批量删除?",
type: "button"
},
{
label: "批量修改",
actionType: "dialog",
dialog: {
title: "批量编辑",
name: "sample-bulk-edit",
body: {
type: "form",
api: "/api/sample/bulkUpdate2",
controls: [
{
type: 'hidden',
name: 'ids'
},
{
type: "text",
name: "engine",
label: "Engine"
}
]
}
},
type: "button"
}
],
columns: [
{
name: "id",
label: "ID",
width: 20,
sortable: true,
type: "text",
toggled: true,
remark: 'Bla bla Bla'
},
{
name: "engine",
label: "Rendering engine",
sortable: true,
searchable: true,
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: false
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
type: "text",
toggled: true
},
{
name: "grade",
label: "CSS grade",
type: "text",
toggled: true
}
]
}
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '增删改查示例',
remark: 'bla bla bla',
body: {
type: 'crud',
api: '/api/sample',
headerToolbar: [
'bulkActions',
{
type: 'columns-toggler',
className: 'pull-right',
align: 'right'
},
{
type: 'drag-toggler',
className: 'pull-right'
},
{
type: 'pagination',
className: 'pull-right'
}
],
itemActions: [
{
type: 'button',
label: '查看',
actionType: 'dialog',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
},
{
type: 'button',
label: '编辑',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'lg',
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'select',
name: 'grade',
label: 'CSS grade',
options: ['A', 'B', 'C', 'D', 'X']
}
]
}
}
},
{
type: 'button',
label: '删除',
actionType: 'ajax',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: 'delete:/api/sample/${ids|raw}',
confirmText: '确定要批量删除?',
type: 'button'
},
{
label: '批量修改',
actionType: 'dialog',
dialog: {
title: '批量编辑',
name: 'sample-bulk-edit',
body: {
type: 'form',
api: '/api/sample/bulkUpdate2',
controls: [
{
type: 'hidden',
name: 'ids'
},
{
type: 'text',
name: 'engine',
label: 'Engine'
}
]
}
},
type: 'button'
}
],
columns: [
{
name: 'id',
label: 'ID',
width: 20,
sortable: true,
type: 'text',
toggled: true,
remark: 'Bla bla Bla'
},
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
searchable: true,
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: false
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
type: 'text',
toggled: true
},
{
name: 'grade',
label: 'CSS grade',
type: 'text',
toggled: true
}
]
}
};

View File

@ -1,131 +1,131 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "操作并下一个",
"remark": "当存在下一条时,支持直接打开下一条操作。",
"body": {
"type": "crud",
"title": "",
"api": "/api/sample/list",
"columnsTogglable": false,
"columns": [
{
"name": "id",
"label": "ID",
"width": 20,
"type": "text",
"toggled": true
},
{
"name": "engine",
"label": "Rendering engine",
"type": "text",
"toggled": true
},
{
"name": "browser",
"label": "Browser",
"type": "text",
"toggled": true
},
{
"type": "operation",
"label": "操作",
"width": 130,
"buttons": [
{
"type": "button",
"icon": "fa fa-pencil",
"actionType": "dialog",
"nextCondition": "true",
"_nextCondition": "可以设置条件比如: data.grade == \"B\"",
"dialog": {
"title": "编辑",
"actions": [
{
"type": "button",
"actionType": "prev",
"level": "info",
"visibleOn": "data.hasPrev",
"label": "上一个"
},
{
"type": "button",
"actionType": "cancel",
"label": "关闭"
},
{
"type": "submit",
"actionType": "next",
"visibleOn": "data.hasNext",
"label": "保存并下一个",
"level": "primary"
},
{
"type": "submit",
"visibleOn": "!data.hasNext",
"label": "保存",
"level": "primary"
},
{
"type": "button",
"actionType": "next",
"level": "info",
"visibleOn": "data.hasNext",
"label": "下一个"
}
],
"body": {
"type": "form",
"name": "sample-edit-form",
"api": "/api/sample/$id",
"controls": [
{
"type": "text",
"name": "engine",
"label": "Engine",
"required": true
},
{
"type": "divider"
},
{
"type": "text",
"name": "browser",
"label": "Browser",
"required": true
},
{
"type": "divider"
},
{
"type": "text",
"name": "platform",
"label": "Platform(s)",
"required": true
},
{
"type": "divider"
},
{
"type": "text",
"name": "version",
"label": "Engine version"
},
{
"type": "divider"
},
{
"type": "text",
"name": "grade",
"label": "CSS grade"
}
]
}
}
}
],
"toggled": true
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '操作并下一个',
remark: '当存在下一条时,支持直接打开下一条操作。',
body: {
type: 'crud',
title: '',
api: '/api/sample/list',
columnsTogglable: false,
columns: [
{
name: 'id',
label: 'ID',
width: 20,
type: 'text',
toggled: true
},
{
name: 'engine',
label: 'Rendering engine',
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
type: 'text',
toggled: true
},
{
type: 'operation',
label: '操作',
width: 130,
buttons: [
{
type: 'button',
icon: 'fa fa-pencil',
actionType: 'dialog',
nextCondition: 'true',
_nextCondition: '可以设置条件比如: data.grade == "B"',
dialog: {
title: '编辑',
actions: [
{
type: 'button',
actionType: 'prev',
level: 'info',
visibleOn: 'data.hasPrev',
label: '上一个'
},
{
type: 'button',
actionType: 'cancel',
label: '关闭'
},
{
type: 'submit',
actionType: 'next',
visibleOn: 'data.hasNext',
label: '保存并下一个',
level: 'primary'
},
{
type: 'submit',
visibleOn: '!data.hasNext',
label: '保存',
level: 'primary'
},
{
type: 'button',
actionType: 'next',
level: 'info',
visibleOn: 'data.hasNext',
label: '下一个'
}
],
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
}
]
}
}
}
],
toggled: true
}
]
}
};

View File

@ -1,83 +1,78 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "Table 全键盘操作示例",
"remark": "bla bla bla",
"body": [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'Table 全键盘操作示例',
remark: 'bla bla bla',
body: [
{
type: 'plain',
className: 'text-danger',
text:
'请通过上下左右键切换单元格,按 `Space` 键进入编辑模式,按 `Enter` 提交编辑,并最后点左上角的全部保存完成操作。'
},
{
type: 'crud',
className: 'm-t',
api: '/api/sample',
quickSaveApi: '/api/sample/bulkUpdate',
quickSaveItemApi: '/api/sample/$id',
columns: [
{
"type": "plain",
"className": "text-danger",
"text": "请通过上下左右键切换单元格,按 `Space` 键进入编辑模式,按 `Enter` 提交编辑,并最后点左上角的全部保存完成操作。"
name: 'id',
label: 'ID',
width: 20,
sortable: true,
type: 'text',
toggled: true
},
{
"type": "crud",
"className": "m-t",
"api": "/api/sample",
"quickSaveApi": "/api/sample/bulkUpdate",
"quickSaveItemApi": "/api/sample/$id",
"columns": [
{
"name": "id",
"label": "ID",
"width": 20,
"sortable": true,
"type": "text",
"toggled": true
},
{
"name": "engine",
"label": "Rendering engine",
"sortable": true,
"quickEdit": {
type: "text",
required: true,
mode: 'inline'
},
"type": "text",
"toggled": true
},
{
"name": "browser",
"label": "Browser",
"sortable": true,
"quickEdit": {
type: "text",
required: true
},
"type": "text",
"toggled": true
},
{
"name": "platform",
"label": "Platform(s)",
"sortable": true,
"quickEdit": true,
"type": "text",
"toggled": true
},
{
"name": "version",
"label": "Engine version",
"quickEdit": true,
"type": "text",
"toggled": true
},
{
"name": "grade",
"label": "CSS grade",
"quickEdit": {
"type": "select",
"options": [
"A",
"B",
"C",
"D",
"X"
]
},
"type": "text",
"toggled": true
}
]
name: 'engine',
label: 'Rendering engine',
sortable: true,
quickEdit: {
type: 'text',
required: true,
mode: 'inline'
},
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
quickEdit: {
type: 'text',
required: true
},
type: 'text',
toggled: true
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
quickEdit: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true
},
{
name: 'grade',
label: 'CSS grade',
quickEdit: {
type: 'select',
options: ['A', 'B', 'C', 'D', 'X']
},
type: 'text',
toggled: true
}
]
}
]
}
]
};

View File

@ -1,214 +1,213 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "增删改查示例",
remark: "bla bla bla",
body: {
type: "crud",
api: "/api/sample",
mode: "list",
draggable: true,
saveOrderApi: {
url: "/api/sample/saveOrder"
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '增删改查示例',
remark: 'bla bla bla',
body: {
type: 'crud',
api: '/api/sample',
mode: 'list',
draggable: true,
saveOrderApi: {
url: '/api/sample/saveOrder'
},
orderField: 'weight',
filter: {
title: '条件搜索',
submitText: '',
controls: [
{
type: 'text',
name: 'keywords',
placeholder: '通过关键字搜索',
addOn: {
label: '搜索',
type: 'submit'
}
},
orderField: "weight",
filter: {
title: "条件搜索",
submitText: "",
controls: [
{
type: "text",
name: "keywords",
placeholder: "通过关键字搜索",
addOn: {
label: "搜索",
type: "submit"
}
},
{
type: "plain",
text: "这只是个示例, 目前搜索对查询结果无效."
}
]
},
bulkActions: [
{
label: "批量删除",
actionType: "ajax",
api: "delete:/api/sample/${ids|raw}",
confirmText: "确定要批量删除?",
type: "button",
level: "danger"
},
{
label: "批量修改",
actionType: "dialog",
level: "info",
type: "button",
dialog: {
title: "批量编辑",
body: {
type: 'form',
api: "/api/sample/bulkUpdate2",
controls: [
{type: 'hidden', name: 'ids'},
{
type: "text",
name: "engine",
label: "Engine"
}
]
}
}
}
],
quickSaveApi: "/api/sample/bulkUpdate",
quickSaveItemApi: "/api/sample/$id",
listItem: {
actions: [
{
type: "button",
icon: "fa fa-eye",
actionType: "dialog",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
icon: "fa fa-pencil",
actionType: "dialog",
dialog: {
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "text",
name: "grade",
label: "CSS grade"
}
]
}
}
},
{
type: "button",
icon: "fa fa-times text-danger",
actionType: "ajax",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
body: [
{
name: "engine",
label: "Rendering engine",
sortable: true,
quickEdit: true
},
[
{
name: "browser",
label: "Browser"
},
{
name: "platform",
label: "Platform(s)"
}
],
{
name: "version",
label: "Engine version"
}
]
{
type: 'plain',
text: '这只是个示例, 目前搜索对查询结果无效.'
}
]
},
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: 'delete:/api/sample/${ids|raw}',
confirmText: '确定要批量删除?',
type: 'button',
level: 'danger'
},
{
label: '批量修改',
actionType: 'dialog',
level: 'info',
type: 'button',
dialog: {
title: '批量编辑',
body: {
type: 'form',
api: '/api/sample/bulkUpdate2',
controls: [
{type: 'hidden', name: 'ids'},
{
type: 'text',
name: 'engine',
label: 'Engine'
}
]
}
}
}
],
quickSaveApi: '/api/sample/bulkUpdate',
quickSaveItemApi: '/api/sample/$id',
listItem: {
actions: [
{
type: 'button',
icon: 'fa fa-eye',
actionType: 'dialog',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-pencil',
actionType: 'dialog',
dialog: {
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-times text-danger',
actionType: 'ajax',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
body: [
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
quickEdit: true
},
[
{
name: 'browser',
label: 'Browser'
},
{
name: 'platform',
label: 'Platform(s)'
}
],
{
name: 'version',
label: 'Engine version'
}
]
}
}
};

View File

@ -1,223 +1,219 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "增删改查示例",
remark: "bla bla bla",
body: {
type: "crud",
api: "/api/sample",
mode: "list",
draggable: true,
saveOrderApi: {
url: "/api/sample/saveOrder"
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '增删改查示例',
remark: 'bla bla bla',
body: {
type: 'crud',
api: '/api/sample',
mode: 'list',
draggable: true,
saveOrderApi: {
url: '/api/sample/saveOrder'
},
orderField: 'weight',
filter: {
title: '条件搜索',
submitText: '',
controls: [
{
type: 'text',
name: 'keywords',
placeholder: '通过关键字搜索',
addOn: {
label: '搜索',
type: 'submit'
}
},
orderField: "weight",
filter: {
title: "条件搜索",
submitText: "",
controls: [
{
type: "text",
name: "keywords",
placeholder: "通过关键字搜索",
addOn: {
label: "搜索",
type: "submit"
}
},
{
type: "plain",
text: "这只是个示例, 目前搜索对查询结果无效."
}
]
},
bulkActions: [
{
label: "批量删除",
actionType: "ajax",
api: "delete:/api/sample/${ids|raw}",
confirmText: "确定要批量删除?",
type: "button",
level: "danger"
},
{
label: "批量修改",
actionType: "dialog",
level: "info",
type: "button",
dialog: {
title: "批量编辑",
body: {
type: 'form',
api: "/api/sample/bulkUpdate2",
controls: [
{type: 'hidden', name: 'ids'},
{
type: "text",
name: "engine",
label: "Engine"
}
]
}
}
}
],
quickSaveApi: "/api/sample/bulkUpdate",
quickSaveItemApi: "/api/sample/$id",
headerToolbar: [
"bulkActions"
],
footerToolbar: [
"load-more"
],
listItem: {
actions: [
{
type: "button",
icon: "fa fa-eye",
actionType: "dialog",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
icon: "fa fa-pencil",
actionType: "dialog",
dialog: {
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "text",
name: "grade",
label: "CSS grade"
}
]
}
}
},
{
type: "button",
icon: "fa fa-times text-danger",
actionType: "ajax",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
body: [
{
name: "engine",
label: "Rendering engine",
sortable: true,
quickEdit: true,
labelClassName: "w-sm pull-left text-muted"
},
[
{
name: "browser",
label: "Browser",
labelClassName: "w-sm pull-left text-muted"
},
{
name: "platform",
label: "Platform(s)",
labelClassName: "w-sm pull-left text-muted"
}
],
{
name: "version",
label: "Engine version",
labelClassName: "w-sm pull-left text-muted"
}
]
{
type: 'plain',
text: '这只是个示例, 目前搜索对查询结果无效.'
}
]
},
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: 'delete:/api/sample/${ids|raw}',
confirmText: '确定要批量删除?',
type: 'button',
level: 'danger'
},
{
label: '批量修改',
actionType: 'dialog',
level: 'info',
type: 'button',
dialog: {
title: '批量编辑',
body: {
type: 'form',
api: '/api/sample/bulkUpdate2',
controls: [
{type: 'hidden', name: 'ids'},
{
type: 'text',
name: 'engine',
label: 'Engine'
}
]
}
}
}
],
quickSaveApi: '/api/sample/bulkUpdate',
quickSaveItemApi: '/api/sample/$id',
headerToolbar: ['bulkActions'],
footerToolbar: ['load-more'],
listItem: {
actions: [
{
type: 'button',
icon: 'fa fa-eye',
actionType: 'dialog',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-pencil',
actionType: 'dialog',
dialog: {
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-times text-danger',
actionType: 'ajax',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
body: [
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
quickEdit: true,
labelClassName: 'w-sm pull-left text-muted'
},
[
{
name: 'browser',
label: 'Browser',
labelClassName: 'w-sm pull-left text-muted'
},
{
name: 'platform',
label: 'Platform(s)',
labelClassName: 'w-sm pull-left text-muted'
}
],
{
name: 'version',
label: 'Engine version',
labelClassName: 'w-sm pull-left text-muted'
}
]
}
}
};

View File

@ -1,202 +1,202 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "一次性加载,前端分页,前端排序",
body: {
type: "crud",
loadDataOnce: true,
api: "/api/sample?waitSeconds=1",
filter: {
title: "条件搜索",
submitText: "",
controls: [
{
type: "text",
name: "keywords",
placeholder: "通过关键字搜索",
addOn: {
label: "搜索",
type: "submit"
}
}
]
},
columns: [
{
name: "id",
label: "ID",
width: 20,
sortable: true,
type: "text",
toggled: true,
remark: 'Bla bla Bla'
},
{
name: "engine",
label: "Rendering engine",
sortable: true,
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: false
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
type: "text",
toggled: true
},
{
name: "grade",
label: "CSS grade",
type: "text",
toggled: true
},
{
type: "operation",
label: "操作",
width: 100,
buttons: [
{
type: "button",
icon: "fa fa-eye",
actionType: "dialog",
tooltip: "查看",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
icon: "fa fa-pencil",
tooltip: "编辑",
actionType: "drawer",
drawer: {
position: 'left',
size: 'lg',
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "select",
name: "grade",
label: "CSS grade",
options: ["A", "B", "C", "D", "X"],
}
]
}
}
},
{
type: "button",
icon: "fa fa-times text-danger",
actionType: "ajax",
tooltip: "删除",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
toggled: true
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '一次性加载,前端分页,前端排序',
body: {
type: 'crud',
loadDataOnce: true,
api: '/api/sample?waitSeconds=1',
filter: {
title: '条件搜索',
submitText: '',
controls: [
{
type: 'text',
name: 'keywords',
placeholder: '通过关键字搜索',
addOn: {
label: '搜索',
type: 'submit'
}
}
]
},
columns: [
{
name: 'id',
label: 'ID',
width: 20,
sortable: true,
type: 'text',
toggled: true,
remark: 'Bla bla Bla'
},
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: false
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
type: 'text',
toggled: true
},
{
name: 'grade',
label: 'CSS grade',
type: 'text',
toggled: true
},
{
type: 'operation',
label: '操作',
width: 100,
buttons: [
{
type: 'button',
icon: 'fa fa-eye',
actionType: 'dialog',
tooltip: '查看',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
]
}
},
{
type: 'button',
icon: 'fa fa-pencil',
tooltip: '编辑',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'lg',
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'select',
name: 'grade',
label: 'CSS grade',
options: ['A', 'B', 'C', 'D', 'X']
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-times text-danger',
actionType: 'ajax',
tooltip: '删除',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
toggled: true
}
]
}
};

View File

@ -1,104 +1,105 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "支持自动合并单元格,从左到右,可配置从左侧起多少列内启动自动合并单元格,当前配置 3",
body: {
type: "table",
data: {
items: [
{
"engine": "Trident",
"browser": "Internet Explorer 4.2",
"platform": "Win 95+",
"version": "4",
"grade": "A"
},
{
"engine": "Trident",
"browser": "Internet Explorer 4.2",
"platform": "Win 95+",
"version": "4",
"grade": "B"
},
{
"engine": "Trident",
"browser": "AOL browser (AOL desktop)",
"platform": "Win 95+",
"version": "4",
"grade": "C"
},
{
"engine": "Trident",
"browser": "AOL browser (AOL desktop)",
"platform": "Win 98",
"version": "3",
"grade": "A"
},
{
"engine": "Trident",
"browser": "AOL browser (AOL desktop)",
"platform": "Win 98",
"version": "4",
"grade": "A"
},
{
"engine": "Gecko",
"browser": "Firefox 1.0",
"platform": "Win 98+ / OSX.2+",
"version": "4",
"grade": "A"
},
{
"engine": "Gecko",
"browser": "Firefox 1.0",
"platform": "Win 98+ / OSX.2+",
"version": "5",
"grade": "A"
},
{
"engine": "Gecko",
"browser": "Firefox 2.0",
"platform": "Win 98+ / OSX.2+",
"version": "5",
"grade": "B"
},
{
"engine": "Gecko",
"browser": "Firefox 2.0",
"platform": "Win 98+ / OSX.2+",
"version": "5",
"grade": "C"
},
{
"engine": "Gecko",
"browser": "Firefox 2.0",
"platform": "Win 98+ / OSX.2+",
"version": "5",
"grade": "D"
}
]
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title:
'支持自动合并单元格,从左到右,可配置从左侧起多少列内启动自动合并单元格,当前配置 3',
body: {
type: 'table',
data: {
items: [
{
engine: 'Trident',
browser: 'Internet Explorer 4.2',
platform: 'Win 95+',
version: '4',
grade: 'A'
},
combineNum: 3, //
columns: [
{
name: "engine",
label: "Rendering engine"
},
{
name: "browser",
label: "Browser"
},
{
name: "platform",
label: "Platform(s)"
},
{
name: "version",
label: "Engine version"
},
{
name: "grade",
label: "CSS grade",
}
]
}
{
engine: 'Trident',
browser: 'Internet Explorer 4.2',
platform: 'Win 95+',
version: '4',
grade: 'B'
},
{
engine: 'Trident',
browser: 'AOL browser (AOL desktop)',
platform: 'Win 95+',
version: '4',
grade: 'C'
},
{
engine: 'Trident',
browser: 'AOL browser (AOL desktop)',
platform: 'Win 98',
version: '3',
grade: 'A'
},
{
engine: 'Trident',
browser: 'AOL browser (AOL desktop)',
platform: 'Win 98',
version: '4',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Firefox 1.0',
platform: 'Win 98+ / OSX.2+',
version: '4',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Firefox 1.0',
platform: 'Win 98+ / OSX.2+',
version: '5',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Firefox 2.0',
platform: 'Win 98+ / OSX.2+',
version: '5',
grade: 'B'
},
{
engine: 'Gecko',
browser: 'Firefox 2.0',
platform: 'Win 98+ / OSX.2+',
version: '5',
grade: 'C'
},
{
engine: 'Gecko',
browser: 'Firefox 2.0',
platform: 'Win 98+ / OSX.2+',
version: '5',
grade: 'D'
}
]
},
combineNum: 3, //
columns: [
{
name: 'engine',
label: 'Rendering engine'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'platform',
label: 'Platform(s)'
},
{
name: 'version',
label: 'Engine version'
},
{
name: 'grade',
label: 'CSS grade'
}
]
}
};

View File

@ -1,197 +1,197 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "支持多层嵌套,列数据中有 children 字段即可。建议不超过10层",
body: {
type: "crud",
api: "/api/mock2/crud/table2",
saveOrderApi: '/api/mock2/form/saveData',
expandConfig: {
expand: 'first',
accordion: true
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '支持多层嵌套,列数据中有 children 字段即可。建议不超过10层',
body: {
type: 'crud',
api: '/api/mock2/crud/table2',
saveOrderApi: '/api/mock2/form/saveData',
expandConfig: {
expand: 'first',
accordion: true
},
draggable: true,
columns: [
{
name: 'id',
label: 'ID',
sortable: true,
type: 'text',
toggled: true,
width: 100
},
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
searchable: true,
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'platform',
label: 'Platform(s)',
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true
},
{
name: 'grade',
label: 'CSS grade',
quickEdit: {
mode: 'inline',
type: 'select',
options: ['A', 'B', 'C', 'D', 'X'],
inputClassName: 'w-xs',
saveImmediately: true
},
draggable: true,
columns: [
{
name: "id",
label: "ID",
sortable: true,
type: "text",
toggled: true,
width: 100
},
{
name: "engine",
label: "Rendering engine",
sortable: true,
searchable: true,
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: true
},
{
name: "platform",
label: "Platform(s)",
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
quickEdit: true,
type: "text",
toggled: true
},
{
name: "grade",
label: "CSS grade",
quickEdit: {
mode: "inline",
type: "select",
options: ["A", "B", "C", "D", "X"],
inputClassName: 'w-xs',
saveImmediately: true
},
type: "text",
toggled: true
},
{
type: "operation",
label: "操作",
width: 100,
buttons: [
{
type: "button",
icon: "fa fa-eye",
actionType: "dialog",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
icon: "fa fa-pencil",
actionType: "drawer",
drawer: {
position: 'left',
size: 'lg',
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "select",
name: "grade",
label: "CSS grade",
options: ["A", "B", "C", "D", "X"],
}
]
}
}
},
{
type: "button",
icon: "fa fa-times text-danger",
actionType: "ajax",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
toggled: true
type: 'text',
toggled: true
},
{
type: 'operation',
label: '操作',
width: 100,
buttons: [
{
type: 'button',
icon: 'fa fa-eye',
actionType: 'dialog',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
]
}
},
{
type: 'button',
icon: 'fa fa-pencil',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'lg',
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'select',
name: 'grade',
label: 'CSS grade',
options: ['A', 'B', 'C', 'D', 'X']
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-times text-danger',
actionType: 'ajax',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
toggled: true
}
]
}
};

View File

@ -1,357 +1,365 @@
export default {
$schema: "http://amis.baidu.com/v2/schemas/page.json#",
title: "增删改查示例",
remark: "bla bla bla",
toolbar: [
{
type: "button",
actionType: "dialog",
label: "新增",
icon: 'fa fa-plus pull-left',
primary: true,
dialog: {
title: "新增",
body: {
type: "form",
name: "sample-edit-form",
api: "post:/api/sample",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "text",
name: "grade",
label: "CSS grade"
}
]
}
$schema: 'http://amis.baidu.com/v2/schemas/page.json#',
title: '增删改查示例',
remark: 'bla bla bla',
toolbar: [
{
type: 'button',
actionType: 'dialog',
label: '新增',
icon: 'fa fa-plus pull-left',
primary: true,
dialog: {
title: '新增',
body: {
type: 'form',
name: 'sample-edit-form',
api: 'post:/api/sample',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
],
body: {
type: "crud",
draggable: true,
api: "/api/sample?waitSeconds=1",
keepItemSelectionOnPageChange: true,
labelTpl: '${id} ${engine}',
filter: {
title: "条件搜索",
submitText: "",
controls: [
{
type: "text",
name: "keywords",
placeholder: "通过关键字搜索",
addOn: {
label: "搜索",
type: "submit"
}
},
{
type: "plain",
text: "这里的表单项可以配置多个"
}
]
},
bulkActions: [
{
label: "批量删除",
actionType: "ajax",
api: "delete:/api/sample/${ids|raw}",
confirmText: "确定要批量删除?"
},
{
label: "批量修改",
actionType: "dialog",
dialog: {
title: "批量编辑",
name: "sample-bulk-edit",
body: {
type: "form",
api: "/api/sample/bulkUpdate2",
controls: [
{
type: 'hidden',
name: 'ids'
},
{
type: "text",
name: "engine",
label: "Engine"
}
]
}
}
}
],
quickSaveApi: "/api/sample/bulkUpdate",
quickSaveItemApi: "/api/sample/$id",
filterTogglable: true,
headerToolbar: ['filter-toggler', 'bulkActions', {
type: 'tpl',
tpl: '定制内容示例:当前有 ${count} 条数据。',
className: 'v-middle'
}, {
type: 'link',
href: 'https://www.baidu.com',
body: '百度一下',
htmlTarget: '_parent',
className: 'v-middle'
}, {
type: 'columns-toggler',
align: 'right'
}, {
type: 'drag-toggler',
align: 'right'
}, {
type: 'pagination',
align: 'right'
}],
footerToolbar: ['statistics', 'switch-per-page', 'pagination'],
columns: [
{
name: "id",
label: "ID",
width: 20,
sortable: true,
type: "text",
toggled: true,
remark: 'Bla bla Bla'
},
{
name: "engine",
label: "Rendering engine",
sortable: true,
searchable: true,
type: "text",
toggled: true
},
{
name: "browser",
label: "Browser",
sortable: true,
type: "text",
toggled: false
},
{
name: "platform",
label: "Platform(s)",
popOver: {
body: {
type: "tpl",
tpl: "偏了一点的popover"
},
offset: {
y: 100
}
},
sortable: true,
type: "text",
toggled: true
},
{
name: "version",
label: "Engine version",
quickEdit: true,
type: "text",
toggled: true,
filterable:{
options:[
{
label:'4',
value:'4'
},
{
label:'5',
value:'5'
},
{
label:'6',
value:'6'
},
]
}
},
{
name: "grade",
label: "CSS grade",
quickEdit: {
mode: "inline",
type: "select",
inputClassName: 'w-xs',
options: ["A", "B", "C", "D", "X"],
saveImmediately: true
},
type: "text",
toggled: true
},
{
type: "operation",
label: "操作",
width: 100,
buttons: [
{
type: "button",
icon: "fa fa-eye",
actionType: "dialog",
tooltip: "查看",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
},
{
type: "divider"
},
{
type: "html",
html:
"<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>"
}
]
}
}
},
{
type: "button",
icon: "fa fa-pencil",
tooltip: "编辑",
actionType: "drawer",
drawer: {
position: 'left',
size: 'lg',
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "select",
name: "grade",
label: "CSS grade",
options: ["A", "B", "C", "D", "X"],
}
]
}
}
},
{
type: "button",
icon: "fa fa-times text-danger",
actionType: "ajax",
tooltip: "删除",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
toggled: true
}
]
}
}
],
body: {
type: 'crud',
draggable: true,
api: '/api/sample?waitSeconds=1',
keepItemSelectionOnPageChange: true,
labelTpl: '${id} ${engine}',
filter: {
title: '条件搜索',
submitText: '',
controls: [
{
type: 'text',
name: 'keywords',
placeholder: '通过关键字搜索',
addOn: {
label: '搜索',
type: 'submit'
}
},
{
type: 'plain',
text: '这里的表单项可以配置多个'
}
]
},
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: 'delete:/api/sample/${ids|raw}',
confirmText: '确定要批量删除?'
},
{
label: '批量修改',
actionType: 'dialog',
dialog: {
title: '批量编辑',
name: 'sample-bulk-edit',
body: {
type: 'form',
api: '/api/sample/bulkUpdate2',
controls: [
{
type: 'hidden',
name: 'ids'
},
{
type: 'text',
name: 'engine',
label: 'Engine'
}
]
}
}
}
],
quickSaveApi: '/api/sample/bulkUpdate',
quickSaveItemApi: '/api/sample/$id',
filterTogglable: true,
headerToolbar: [
'filter-toggler',
'bulkActions',
{
type: 'tpl',
tpl: '定制内容示例:当前有 ${count} 条数据。',
className: 'v-middle'
},
{
type: 'link',
href: 'https://www.baidu.com',
body: '百度一下',
htmlTarget: '_parent',
className: 'v-middle'
},
{
type: 'columns-toggler',
align: 'right'
},
{
type: 'drag-toggler',
align: 'right'
},
{
type: 'pagination',
align: 'right'
}
],
footerToolbar: ['statistics', 'switch-per-page', 'pagination'],
columns: [
{
name: 'id',
label: 'ID',
width: 20,
sortable: true,
type: 'text',
toggled: true,
remark: 'Bla bla Bla'
},
{
name: 'engine',
label: 'Rendering engine',
sortable: true,
searchable: true,
type: 'text',
toggled: true
},
{
name: 'browser',
label: 'Browser',
sortable: true,
type: 'text',
toggled: false
},
{
name: 'platform',
label: 'Platform(s)',
popOver: {
body: {
type: 'tpl',
tpl: '偏了一点的popover'
},
offset: {
y: 100
}
},
sortable: true,
type: 'text',
toggled: true
},
{
name: 'version',
label: 'Engine version',
quickEdit: true,
type: 'text',
toggled: true,
filterable: {
options: [
{
label: '4',
value: '4'
},
{
label: '5',
value: '5'
},
{
label: '6',
value: '6'
}
]
}
},
{
name: 'grade',
label: 'CSS grade',
quickEdit: {
mode: 'inline',
type: 'select',
inputClassName: 'w-xs',
options: ['A', 'B', 'C', 'D', 'X'],
saveImmediately: true
},
type: 'text',
toggled: true
},
{
type: 'operation',
label: '操作',
width: 100,
buttons: [
{
type: 'button',
icon: 'fa fa-eye',
actionType: 'dialog',
tooltip: '查看',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
},
{
type: 'divider'
},
{
type: 'html',
html:
'<p>添加其他 <span>Html 片段</span> 需要支持变量替换todo.</p>'
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-pencil',
tooltip: '编辑',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'lg',
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'select',
name: 'grade',
label: 'CSS grade',
options: ['A', 'B', 'C', 'D', 'X']
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-times text-danger',
actionType: 'ajax',
tooltip: '删除',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
toggled: true
}
]
}
};

View File

@ -1,92 +1,92 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "Test 信息:${page}",
body: {
"type": "crud",
"api": "/api/sample",
"syncLocation": false,
"title": null,
"columns": [
{
"name": "id",
"label": "ID",
"width": 20
},
{
"name": "engine",
"label": "Rendering engine",
"sortable": true
},
{
"name": "grade",
"type": "map",
"label": "Rendering engine",
"map": {
"A": "<span class='label label-info'>A</span>",
"B": "<span class='label label-success'>B</span>",
"C": "<span class='label label-primary'>C</span>",
"X": "<span class='label label-danger'>X</span>",
"*": "Unkown"
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'Test 信息:${page}',
body: {
type: 'crud',
api: '/api/sample',
syncLocation: false,
title: null,
columns: [
{
name: 'id',
label: 'ID',
width: 20
},
{
name: 'engine',
label: 'Rendering engine',
sortable: true
},
{
name: 'grade',
type: 'map',
label: 'Rendering engine',
map: {
A: "<span class='label label-info'>A</span>",
B: "<span class='label label-success'>B</span>",
C: "<span class='label label-primary'>C</span>",
X: "<span class='label label-danger'>X</span>",
'*': 'Unkown'
}
},
{
type: 'operation',
label: '操作',
width: 200,
buttons: [
{
type: 'button-group',
buttons: [
{
type: 'button',
label: '查看',
actionType: 'dialog',
dialog: {
disabled: true,
body: {
type: 'form',
controls: [
{
name: 'engine',
label: 'Rendering engine',
type: 'static'
}
]
}
}
},
{
"type": "operation",
"label": "操作",
"width": 200,
"buttons": [
{
"type": "button-group",
"buttons": [
{
"type": "button",
"label": "查看",
"actionType": "dialog",
"dialog": {
"disabled": true,
"body": {
"type": "form",
"controls": [
{
"name": "engine",
"label": "Rendering engine",
"type": "static"
}
]
}
}
},
},
{
"type": "button",
"label": "编辑",
"actionType": "dialog",
"dialog": {
"body": {
"api": "/api/sample/$id",
"type": "form",
"controls": [
{
"name": "engine",
"label": "Rendering engine",
"type": "text"
}
]
}
}
},
{
type: 'button',
label: '编辑',
actionType: 'dialog',
dialog: {
body: {
api: '/api/sample/$id',
type: 'form',
controls: [
{
name: 'engine',
label: 'Rendering engine',
type: 'text'
}
]
}
}
},
{
"type": "button",
"label": "删除",
"level": "danger",
"actionType": "ajax",
"confirmText": "确定?",
"api": "delete:/api/sample/$id"
}
]
}
]
}
{
type: 'button',
label: '删除',
level: 'danger',
actionType: 'ajax',
confirmText: '确定?',
api: 'delete:/api/sample/$id'
}
]
}
]
}
}
]
}
};

View File

@ -1,83 +1,89 @@
export default {
type: 'page',
title: '轮播图',
data: {
carousel0: [
'https://hiphotos.baidu.com/fex/%70%69%63/item/bd3eb13533fa828b13b24500f31f4134960a5a44.jpg',
'https://video-react.js.org/assets/poster.png',
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg'
],
carousel1: [
{
html: '<div style="width: 100%; height: 300px; background: #e3e3e3; text-align: center; line-height: 300px;">carousel data in form</div>'
},
{
image: 'https://hiphotos.baidu.com/fex/%70%69%63/item/bd3eb13533fa828b13b24500f31f4134960a5a44.jpg'
},
{
image: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg'
}
]
},
body: [
type: 'page',
title: '轮播图',
data: {
carousel0: [
'https://hiphotos.baidu.com/fex/%70%69%63/item/bd3eb13533fa828b13b24500f31f4134960a5a44.jpg',
'https://video-react.js.org/assets/poster.png',
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg'
],
carousel1: [
{
html:
'<div style="width: 100%; height: 300px; background: #e3e3e3; text-align: center; line-height: 300px;">carousel data in form</div>'
},
{
image:
'https://hiphotos.baidu.com/fex/%70%69%63/item/bd3eb13533fa828b13b24500f31f4134960a5a44.jpg'
},
{
image:
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg'
}
]
},
body: [
{
type: 'grid',
columns: [
{
type: 'grid',
columns: [
{
type: 'panel',
title: '直接页面配置',
body: {
type: 'carousel',
controlsTheme: 'light',
height: '300',
options: [
{
image: 'https://video-react.js.org/assets/poster.png'
},
{
html: '<div style="width: 100%; height: 300px; background: #e3e3e3; text-align: center; line-height: 300px;">carousel data</div>'
},
{
image: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg'
}
]
}
},
{
type: 'panel',
title: '使用itemSchema配置',
body: {
type: 'carousel',
name: 'carousel0',
controlsTheme: 'dark',
height: '300',
itemSchema: {
type: 'tpl',
tpl: '<div style="height: 100%; background-image: url(<%=data.item%>); background-position: center center; background-size: cover;"></div>'
}
}
}
type: 'panel',
title: '直接页面配置',
body: {
type: 'carousel',
controlsTheme: 'light',
height: '300',
options: [
{
image: 'https://video-react.js.org/assets/poster.png'
},
{
html:
'<div style="width: 100%; height: 300px; background: #e3e3e3; text-align: center; line-height: 300px;">carousel data</div>'
},
{
image:
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg'
}
]
}
},
{
type: 'grid',
columns: [
{
type: 'form',
title: '表单内展示',
sm: 6,
controls: [
{
type: 'carousel',
controlsTheme: 'dark',
name: 'carousel1',
label: 'carousel',
animation: 'slide',
height: '300'
}
]
}
]
type: 'panel',
title: '使用itemSchema配置',
body: {
type: 'carousel',
name: 'carousel0',
controlsTheme: 'dark',
height: '300',
itemSchema: {
type: 'tpl',
tpl:
'<div style="height: 100%; background-image: url(<%=data.item%>); background-position: center center; background-size: cover;"></div>'
}
}
}
]
}
]
},
{
type: 'grid',
columns: [
{
type: 'form',
title: '表单内展示',
sm: 6,
controls: [
{
type: 'carousel',
controlsTheme: 'dark',
name: 'carousel1',
label: 'carousel',
animation: 'slide',
height: '300'
}
]
}
]
}
]
};

View File

@ -1,197 +1,160 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "图表示例",
"body": [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '图表示例',
body: [
{
type: 'grid',
columns: [
{
"type": "grid",
"columns": [
{
"type": "panel",
"title": "本地配置示例 支持交互",
"name": "chart-local",
"body": [
{
"type": "chart",
"config": {
"title": {
"text": "极坐标双数值轴"
},
"legend": {
"data": [
"line"
]
},
"polar": {
"center": [
"50%",
"54%"
]
},
"tooltip": {
"trigger": "axis",
"axisPointer": {
"type": "cross"
}
},
"angleAxis": {
"type": "value",
"startAngle": 0
},
"radiusAxis": {
"min": 0
},
"series": [
{
"coordinateSystem": "polar",
"name": "line",
"type": "line",
"showSymbol": false,
"data": [
[
0,
0
],
[
0.03487823687206265,
1
],
[
0.06958655048003272,
2
],
[
0.10395584540887964,
3
],
[
0.13781867790849958,
4
],
[
0.17101007166283433,
5
],
[
0.2033683215379001,
6
],
[
0.2347357813929454,
7
],
[
0.26495963211660245,
8
],
[
0.2938926261462365,
9
],
[
0.3213938048432697,
10
]
]
}
],
"animationDuration": 2000
},
clickAction: {
actionType: 'dialog',
dialog: {
title: '详情',
body: [
{
type: 'tpl',
tpl: '<span>当前选中值 ${value|json}<span>'
},
{
"type": "chart",
"api": "/api/mock2/chart/chart1"
}
]
}
}
}
]
type: 'panel',
title: '本地配置示例 支持交互',
name: 'chart-local',
body: [
{
type: 'chart',
config: {
title: {
text: '极坐标双数值轴'
},
{
"type": "panel",
"title": "远程图表示例(返回值带function)",
"name": "chart-remote",
"body": [
{
"type": "chart",
"api": "/api/mock2/chart/chart1"
}
]
}
]
},
{
"type": "panel",
"title": "Form+chart组合",
"body": [
{
"type": "form",
"title": "过滤条件",
"target": "chart1,chart2",
"submitOnInit":true,
"className": "m-b",
"wrapWithPanel": false,
"mode": "inline",
"controls": [
{
"type": "date",
"label": "开始日期",
"name": "starttime",
"value": "-8days",
"maxDate": "${endtime}"
},
{
"type": "date",
"label": "结束日期",
"name": "endtime",
"value": "-1days",
"minDate": "${starttime}"
},
legend: {
data: ['line']
},
polar: {
center: ['50%', '54%']
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
angleAxis: {
type: 'value',
startAngle: 0
},
radiusAxis: {
min: 0
},
series: [
{
"type": "text",
"label": "条件",
"name": "name",
"addOn": {
"type": "submit",
"label": "搜索",
"level": "primary"
}
coordinateSystem: 'polar',
name: 'line',
type: 'line',
showSymbol: false,
data: [
[0, 0],
[0.03487823687206265, 1],
[0.06958655048003272, 2],
[0.10395584540887964, 3],
[0.13781867790849958, 4],
[0.17101007166283433, 5],
[0.2033683215379001, 6],
[0.2347357813929454, 7],
[0.26495963211660245, 8],
[0.2938926261462365, 9],
[0.3213938048432697, 10]
]
}
],
"actions": []
animationDuration: 2000
},
{
type: 'divider'
},
{
"type": "grid",
"className": "m-t-lg",
"columns": [
{
"type": "chart",
"name": "chart1",
"initFetch": false,
"api": "/api/mock2/chart/chart?name=$name&starttime=${starttime}&endtime=${endtime}"
},
{
"type": "chart",
"name": "chart2",
"initFetch": false,
"api": "/api/mock2/chart/chart2?name=$name"
}
]
clickAction: {
actionType: 'dialog',
dialog: {
title: '详情',
body: [
{
type: 'tpl',
tpl: '<span>当前选中值 ${value|json}<span>'
},
{
type: 'chart',
api: '/api/mock2/chart/chart1'
}
]
}
}
]
}
]
}
}
]
},
{
type: 'panel',
title: '远程图表示例(返回值带function)',
name: 'chart-remote',
body: [
{
type: 'chart',
api: '/api/mock2/chart/chart1'
}
]
}
]
},
{
type: 'panel',
title: 'Form+chart组合',
body: [
{
type: 'form',
title: '过滤条件',
target: 'chart1,chart2',
submitOnInit: true,
className: 'm-b',
wrapWithPanel: false,
mode: 'inline',
controls: [
{
type: 'date',
label: '开始日期',
name: 'starttime',
value: '-8days',
maxDate: '${endtime}'
},
{
type: 'date',
label: '结束日期',
name: 'endtime',
value: '-1days',
minDate: '${starttime}'
},
{
type: 'text',
label: '条件',
name: 'name',
addOn: {
type: 'submit',
label: '搜索',
level: 'primary'
}
}
],
actions: []
},
{
type: 'divider'
},
{
type: 'grid',
className: 'm-t-lg',
columns: [
{
type: 'chart',
name: 'chart1',
initFetch: false,
api:
'/api/mock2/chart/chart?name=$name&starttime=${starttime}&endtime=${endtime}'
},
{
type: 'chart',
name: 'chart2',
initFetch: false,
api: '/api/mock2/chart/chart2?name=$name'
}
]
}
]
}
]
};

View File

@ -1,413 +1,413 @@
export default {
type: 'page',
title: 'Drawer',
body: [
type: 'page',
title: 'Drawer',
body: [
{
type: 'button-toolbar',
className: 'block',
buttons: [
{
type: 'button-toolbar',
className: "block",
buttons: [
{
type: 'button',
label: '左侧弹出-极小框',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'xs',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '左侧弹出-小框',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '左侧弹出-中框',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'md',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '左侧弹出-大框',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '左侧弹出-超大',
actionType: 'drawer',
level: 'danger',
drawer: {
position: 'left',
size: 'xl',
title: '提示',
body: '这是个简单的弹框'
}
},
]
type: 'button',
label: '左侧弹出-极小框',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'xs',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button-toolbar',
className: 'block m-t',
buttons: [
{
type: 'button',
label: '右侧弹出-极小框',
level: 'success',
actionType: 'drawer',
drawer: {
position: 'right',
size: 'xs',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '右侧弹出-小框',
level: 'success',
actionType: 'drawer',
drawer: {
position: 'right',
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '右侧弹出-中框',
level: 'success',
actionType: 'drawer',
drawer: {
position: 'right',
size: 'md',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '右侧弹出-大框',
level: 'success',
actionType: 'drawer',
drawer: {
position: 'right',
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '右侧弹出-超大',
level: 'danger',
actionType: 'drawer',
drawer: {
size: 'xl',
position: 'right',
title: '提示',
body: '这是个简单的弹框'
}
}
]
type: 'button',
label: '左侧弹出-小框',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button-toolbar',
className: 'block m-t',
buttons: [
{
type: 'button',
label: '顶部弹出-极小框',
actionType: 'drawer',
level: 'info',
drawer: {
position: 'top',
size: 'xs',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '顶部弹出-小框',
level: 'info',
actionType: 'drawer',
drawer: {
position: 'top',
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '顶部弹出-中框',
actionType: 'drawer',
level: 'info',
drawer: {
position: 'top',
size: 'md',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '顶部弹出-大框',
actionType: 'drawer',
level: 'info',
drawer: {
position: 'top',
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '顶部弹出 - 超大',
level: 'danger',
actionType: 'drawer',
drawer: {
position: 'top',
size: 'xl',
title: '提示',
body: '这是个简单的弹框'
}
}
]
type: 'button',
label: '左侧弹出-中框',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'md',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button-toolbar',
className: 'block m-t',
buttons: [
{
type: 'button',
label: '底部弹出-极小框',
actionType: 'drawer',
level: 'primary',
drawer: {
position: 'bottom',
size: 'xs',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '底部弹出-小框',
level: 'primary',
actionType: 'drawer',
drawer: {
position: 'bottom',
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '底部弹出-中框',
actionType: 'drawer',
level: 'primary',
drawer: {
position: 'bottom',
size: 'md',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '底部弹出-大框',
actionType: 'drawer',
level: 'primary',
drawer: {
position: 'bottom',
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '底部弹出-超大',
level: 'danger',
actionType: 'drawer',
drawer: {
position: 'bottom',
size: 'xl',
title: '提示',
body: '这是个简单的弹框'
}
}
]
type: 'button',
label: '左侧弹出-大框',
actionType: 'drawer',
drawer: {
position: 'left',
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button-toolbar',
className: 'block m-t',
buttons: [
{
type: 'button',
label: '多级弹框',
actionType: 'drawer',
level: 'danger',
drawer: {
title: '提示',
body: '这是个简单的弹框',
closeOnEsc: true,
actions: [
{
type: 'button',
actionType: 'confirm',
label: '确认',
primary: true
},
{
type: 'button',
actionType: 'drawer',
label: '再弹一个',
drawer: {
position: 'left',
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'drawer',
label: '来吧',
level: 'info',
drawer: {
position: 'right',
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'confirm',
label: '可以了',
primary: true
}
]
}
}
]
}
}
]
}
},
{
type: 'button',
label: '交叉测试',
actionType: 'drawer',
className: 'm-l-xs',
level: 'danger',
drawer: {
title: '提示',
closeOnEsc: true,
body: '这是个简单的弹框',
actions: [
{
type: 'button',
actionType: 'confirm',
label: '确认',
primary: true
},
{
type: 'button',
actionType: 'dialog',
closeOnEsc: true,
label: '再弹一个',
dialog: {
position: 'left',
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'drawer',
label: '来吧',
level: 'info',
drawer: {
position: 'right',
title: '弹框中的弹框',
body: '如果你想,可以无限弹下去',
closeOnEsc: true,
actions: [
{
type: 'button',
actionType: 'confirm',
label: '可以了',
primary: true
}
]
}
}
]
}
}
]
}
},
{
type: 'button',
label: '可拉拽调整大小',
actionType: 'drawer',
level: 'danger',
drawer: {
title: '提示',
closeOnEsc: true,
resizable: true,
body: '这是个简单的弹框',
}
},
]
type: 'button',
label: '左侧弹出-超大',
actionType: 'drawer',
level: 'danger',
drawer: {
position: 'left',
size: 'xl',
title: '提示',
body: '这是个简单的弹框'
}
}
],
}
]
},
{
type: 'button-toolbar',
className: 'block m-t',
buttons: [
{
type: 'button',
label: '右侧弹出-极小框',
level: 'success',
actionType: 'drawer',
drawer: {
position: 'right',
size: 'xs',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '右侧弹出-小框',
level: 'success',
actionType: 'drawer',
drawer: {
position: 'right',
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '右侧弹出-中框',
level: 'success',
actionType: 'drawer',
drawer: {
position: 'right',
size: 'md',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '右侧弹出-大框',
level: 'success',
actionType: 'drawer',
drawer: {
position: 'right',
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '右侧弹出-超大',
level: 'danger',
actionType: 'drawer',
drawer: {
size: 'xl',
position: 'right',
title: '提示',
body: '这是个简单的弹框'
}
}
]
},
{
type: 'button-toolbar',
className: 'block m-t',
buttons: [
{
type: 'button',
label: '顶部弹出-极小框',
actionType: 'drawer',
level: 'info',
drawer: {
position: 'top',
size: 'xs',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '顶部弹出-小框',
level: 'info',
actionType: 'drawer',
drawer: {
position: 'top',
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '顶部弹出-中框',
actionType: 'drawer',
level: 'info',
drawer: {
position: 'top',
size: 'md',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '顶部弹出-大框',
actionType: 'drawer',
level: 'info',
drawer: {
position: 'top',
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '顶部弹出 - 超大',
level: 'danger',
actionType: 'drawer',
drawer: {
position: 'top',
size: 'xl',
title: '提示',
body: '这是个简单的弹框'
}
}
]
},
{
type: 'button-toolbar',
className: 'block m-t',
buttons: [
{
type: 'button',
label: '底部弹出-极小框',
actionType: 'drawer',
level: 'primary',
drawer: {
position: 'bottom',
size: 'xs',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '底部弹出-小框',
level: 'primary',
actionType: 'drawer',
drawer: {
position: 'bottom',
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '底部弹出-中框',
actionType: 'drawer',
level: 'primary',
drawer: {
position: 'bottom',
size: 'md',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '底部弹出-大框',
actionType: 'drawer',
level: 'primary',
drawer: {
position: 'bottom',
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '底部弹出-超大',
level: 'danger',
actionType: 'drawer',
drawer: {
position: 'bottom',
size: 'xl',
title: '提示',
body: '这是个简单的弹框'
}
}
]
},
{
type: 'button-toolbar',
className: 'block m-t',
buttons: [
{
type: 'button',
label: '多级弹框',
actionType: 'drawer',
level: 'danger',
drawer: {
title: '提示',
body: '这是个简单的弹框',
closeOnEsc: true,
actions: [
{
type: 'button',
actionType: 'confirm',
label: '确认',
primary: true
},
{
type: 'button',
actionType: 'drawer',
label: '再弹一个',
drawer: {
position: 'left',
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'drawer',
label: '来吧',
level: 'info',
drawer: {
position: 'right',
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'confirm',
label: '可以了',
primary: true
}
]
}
}
]
}
}
]
}
},
{
type: 'button',
label: '交叉测试',
actionType: 'drawer',
className: 'm-l-xs',
level: 'danger',
drawer: {
title: '提示',
closeOnEsc: true,
body: '这是个简单的弹框',
actions: [
{
type: 'button',
actionType: 'confirm',
label: '确认',
primary: true
},
{
type: 'button',
actionType: 'dialog',
closeOnEsc: true,
label: '再弹一个',
dialog: {
position: 'left',
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'drawer',
label: '来吧',
level: 'info',
drawer: {
position: 'right',
title: '弹框中的弹框',
body: '如果你想,可以无限弹下去',
closeOnEsc: true,
actions: [
{
type: 'button',
actionType: 'confirm',
label: '可以了',
primary: true
}
]
}
}
]
}
}
]
}
},
{
type: 'button',
label: '可拉拽调整大小',
actionType: 'drawer',
level: 'danger',
drawer: {
title: '提示',
closeOnEsc: true,
resizable: true,
body: '这是个简单的弹框'
}
}
]
}
]
};

View File

@ -1,266 +1,266 @@
export default {
type: 'page',
title: 'Dialog',
body: [
type: 'page',
title: 'Dialog',
body: [
{
type: 'button-toolbar',
className: 'm-b',
buttons: [
{
type: 'button-toolbar',
className: 'm-b',
buttons: [
{
type: 'button',
label: '打开弹框',
actionType: 'dialog',
dialog: {
title: '提示',
closeOnEsc: true,
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '多级弹框',
actionType: 'dialog',
dialog: {
title: '提示',
closeOnEsc: true,
body: '这是个简单的弹框',
actions: [
{
type: 'button',
actionType: 'confirm',
label: '确认',
primary: true
},
{
type: 'button',
actionType: 'dialog',
label: '再弹一个',
dialog: {
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'dialog',
label: '来吧',
level: 'info',
dialog: {
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'confirm',
label: '不弹了',
primary: true
}
]
}
}
]
}
}
]
}
},
{
type: 'button',
label: '弹个表单',
actionType: 'dialog',
dialog: {
title: '在弹框中的表单',
closeOnEsc: true,
actions: [
{
label: '取消',
actionType: 'close',
type: 'button'
},
{
label: '确认',
actionType: 'confirm',
type: 'button',
level: 'primary'
},
{
label: '提交不关闭',
actionType: 'submit',
close: false,
type: 'button',
api: '/api/mock2/form/saveForm?waitSeconds=2',
level: 'primary'
},
{
label: '保存不关闭',
actionType: 'ajax',
type: 'button',
api: '/api/mock2/form/saveForm?waitSeconds=4',
level: 'info'
},
{
type: 'button',
label: 'Feedback',
close: true,
actionType: 'ajax',
api: '/api/mock2/form/initData?waitSeconds=2',
tooltip: '点击我后会发送一个请求,请求回来后,弹出一个框。',
feedback: {
title: '操作成功',
body: 'xxx 已操作成功'
}
}
],
body: {
type: "form",
api: "/api/mock2/form/saveForm?waitSeconds=2",
title: "常规模式",
mode: "normal",
controls: [
{
type: "email",
name: "email",
required: true,
placeholder: "请输入邮箱",
label: "邮箱"
},
{
type: "password",
name: "password",
label: "密码",
required: true,
placeholder: "请输入密码"
},
{
type: "checkbox",
name: "rememberMe",
label: "记住登录"
}
]
}
}
},
{
type: 'button',
label: '再弹个表单',
actionType: 'dialog',
dialog: {
title: '在弹框中的表单',
actions: [
{
label: '取消',
actionType: 'close',
type: 'button'
},
{
label: '确认',
actionType: 'confirm',
type: 'button',
level: 'primary',
disabledOn: '!data.rememberMe'
}
],
body: {
type: "form",
api: "/api/mock2/form/saveForm?waitSeconds=2",
title: "常规模式",
mode: "normal",
controls: [
{
type: "checkbox",
name: "rememberMe",
label: "勾上我才可以确认"
}
]
}
}
},
{
type: 'button',
label: 'Feedback',
actionType: 'ajax',
api: '/api/mock2/form/initData?waitSeconds=2',
tooltip: '点击我后会发送一个请求,请求回来后,弹出一个框。',
feedback: {
title: '操作成功',
closeOnEsc: true,
body: 'xxx 已操作成功'
}
},
{
type: 'button',
label: 'Feedback2',
actionType: 'ajax',
api: '/api/mock2/form/initData?waitSeconds=2',
tooltip: '可以根据条件弹出比如这个栗子看当前时间戳是否可以整除3',
feedback: {
visibleOn: '!(this.date % 3)',
title: '操作成功',
body: '当前时间戳: <code>${date}</code>'
}
},
]
type: 'button',
label: '打开弹框',
actionType: 'dialog',
dialog: {
title: '提示',
closeOnEsc: true,
body: '这是个简单的弹框'
}
},
{
type: "button-toolbar",
className: 'm-l-none',
buttons: [
{
type: 'button',
label: 'sm 弹框',
actionType: 'dialog',
dialog: {
size: "sm",
title: '提示',
body: '这是个简单的弹框'
}
},
type: 'button',
label: '多级弹框',
actionType: 'dialog',
dialog: {
title: '提示',
closeOnEsc: true,
body: '这是个简单的弹框',
actions: [
{
type: 'button',
actionType: 'confirm',
label: '确认',
primary: true
},
{
type: 'button',
label: '标准 弹框',
actionType: 'dialog',
dialog: {
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: 'lg 弹框',
actionType: 'dialog',
dialog: {
size: "lg",
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: 'xl 弹框',
actionType: 'dialog',
dialog: {
size: "xl",
title: '提示',
body: '这是个简单的弹框'
{
type: 'button',
actionType: 'dialog',
label: '再弹一个',
dialog: {
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'dialog',
label: '来吧',
level: 'info',
dialog: {
title: '弹框中的弹框',
closeOnEsc: true,
body: '如果你想,可以无限弹下去',
actions: [
{
type: 'button',
actionType: 'confirm',
label: '不弹了',
primary: true
}
]
}
}
]
}
}
]
}
},
{
type: 'button',
label: '弹个表单',
actionType: 'dialog',
dialog: {
title: '在弹框中的表单',
closeOnEsc: true,
actions: [
{
label: '取消',
actionType: 'close',
type: 'button'
},
{
label: '确认',
actionType: 'confirm',
type: 'button',
level: 'primary'
},
{
label: '提交不关闭',
actionType: 'submit',
close: false,
type: 'button',
api: '/api/mock2/form/saveForm?waitSeconds=2',
level: 'primary'
},
{
label: '保存不关闭',
actionType: 'ajax',
type: 'button',
api: '/api/mock2/form/saveForm?waitSeconds=4',
level: 'info'
},
{
type: 'button',
label: 'Feedback',
close: true,
actionType: 'ajax',
api: '/api/mock2/form/initData?waitSeconds=2',
tooltip: '点击我后会发送一个请求,请求回来后,弹出一个框。',
feedback: {
title: '操作成功',
body: 'xxx 已操作成功'
}
}
],
body: {
type: 'form',
api: '/api/mock2/form/saveForm?waitSeconds=2',
title: '常规模式',
mode: 'normal',
controls: [
{
type: 'email',
name: 'email',
required: true,
placeholder: '请输入邮箱',
label: '邮箱'
},
{
type: 'password',
name: 'password',
label: '密码',
required: true,
placeholder: '请输入密码'
},
{
type: 'checkbox',
name: 'rememberMe',
label: '记住登录'
}
]
}
}
},
{
type: 'button',
label: '再弹个表单',
actionType: 'dialog',
dialog: {
title: '在弹框中的表单',
actions: [
{
label: '取消',
actionType: 'close',
type: 'button'
},
{
label: '确认',
actionType: 'confirm',
type: 'button',
level: 'primary',
disabledOn: '!data.rememberMe'
}
],
body: {
type: 'form',
api: '/api/mock2/form/saveForm?waitSeconds=2',
title: '常规模式',
mode: 'normal',
controls: [
{
type: 'checkbox',
name: 'rememberMe',
label: '勾上我才可以确认'
}
]
}
}
},
{
type: 'button',
label: 'Feedback',
actionType: 'ajax',
api: '/api/mock2/form/initData?waitSeconds=2',
tooltip: '点击我后会发送一个请求,请求回来后,弹出一个框。',
feedback: {
title: '操作成功',
closeOnEsc: true,
body: 'xxx 已操作成功'
}
},
{
type: 'button',
label: 'Feedback2',
actionType: 'ajax',
api: '/api/mock2/form/initData?waitSeconds=2',
tooltip: '可以根据条件弹出比如这个栗子看当前时间戳是否可以整除3',
feedback: {
visibleOn: '!(this.date % 3)',
title: '操作成功',
body: '当前时间戳: <code>${date}</code>'
}
}
],
}
]
},
{
type: 'button-toolbar',
className: 'm-l-none',
buttons: [
{
type: 'button',
label: 'sm 弹框',
actionType: 'dialog',
dialog: {
size: 'sm',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: '标准 弹框',
actionType: 'dialog',
dialog: {
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: 'lg 弹框',
actionType: 'dialog',
dialog: {
size: 'lg',
title: '提示',
body: '这是个简单的弹框'
}
},
{
type: 'button',
label: 'xl 弹框',
actionType: 'dialog',
dialog: {
size: 'xl',
title: '提示',
body: '这是个简单的弹框'
}
}
]
}
]
};

File diff suppressed because it is too large Load Diff

View File

@ -2,46 +2,46 @@ import React from 'react';
import makeSchemaRenderer from './SchemaRender';
const FormComponent = makeSchemaRenderer({
type: 'form',
mode: 'inline',
wrapWithPanel: false,
className: 'pull-right m-t-sm m-r',
controls: [{
"type": "input-group",
"size": "sm",
"controls": [
{
"type": "icon",
"addOnclassName": "no-bg",
"className": "text-sm",
"icon": "search",
"vendor": "iconfont"
},
{
"type": "text",
"placeholder": "搜索文档",
"inputClassName": "b-l-none p-l-none",
"name": "docsearch"
}
]
}]
})
type: 'form',
mode: 'inline',
wrapWithPanel: false,
className: 'pull-right m-t-sm m-r',
controls: [
{
type: 'input-group',
size: 'sm',
controls: [
{
type: 'icon',
addOnclassName: 'no-bg',
className: 'text-sm',
icon: 'search',
vendor: 'iconfont'
},
{
type: 'text',
placeholder: '搜索文档',
inputClassName: 'b-l-none p-l-none',
name: 'docsearch'
}
]
}
]
});
export default class DocSearch extends React.Component {
componentDidMount() {
const inputSelector = 'input[name="docsearch"]';
docsearch({
appId: '3W0NHYOWPE',
apiKey: '469f5cf3d54f9b86127970f913dc0725',
indexName: 'gh_pages',
inputSelector,
debug: false,
});
}
componentDidMount() {
const inputSelector = 'input[name="docsearch"]';
docsearch({
appId: '3W0NHYOWPE',
apiKey: '469f5cf3d54f9b86127970f913dc0725',
indexName: 'gh_pages',
inputSelector,
debug: false
});
}
render() {
return (
<FormComponent showCode={false} theme={this.props.theme} />
);
}
}
render() {
return <FormComponent showCode={false} theme={this.props.theme} />;
}
}

View File

@ -3,49 +3,62 @@ import Editor from '../../src/editor/Editor';
import Switch from '../../src/components/Switch';
import Button from '../../src/components/Button';
import schema from './Form/Test';
import { Portal } from 'react-overlays';
import {Portal} from 'react-overlays';
export default class AMisSchemaEditor extends React.Component {
state = {
preview: localStorage.getItem('editting_preview') ? true : false,
schema: localStorage.getItem('editting_schema')
? JSON.parse(localStorage.getItem('editting_schema'))
: schema
};
state = {
preview: localStorage.getItem('editting_preview') ? true : false,
schema: localStorage.getItem('editting_schema') ? JSON.parse(localStorage.getItem('editting_schema')) : schema
};
handleChange = value => {
localStorage.setItem('editting_schema', JSON.stringify(value));
handleChange = (value) => {
localStorage.setItem('editting_schema', JSON.stringify(value));
this.setState({
schema: value
});
};
handlePreviewChange = preview => {
localStorage.setItem('editting_preview', preview ? 'true' : '');
this.setState({
schema: value
});
}
handlePreviewChange = (preview) => {
localStorage.setItem('editting_preview', preview ? 'true' : '');
this.setState({
preview: !!preview
});
};
clearCache = () => {
localStorage.removeItem('editting_schema');
this.setState({
schema: schema
});
};
this.setState({
preview: !!preview
});
}
clearCache = () => {
localStorage.removeItem('editting_schema');
this.setState({
schema: schema
});
}
render() {
return (
<div className="h-full">
<Portal container={() => document.querySelector('#headerBar')}>
<div className="inline m-l">
预览{' '}
<Switch
value={this.state.preview}
onChange={this.handlePreviewChange}
className="v-middle"
inline
/>
<Button size="sm" className="m-l" onClick={this.clearCache}>
清除缓存
</Button>
</div>
</Portal>
render() {
return (
<div className="h-full">
<Portal container={() => document.querySelector('#headerBar')}>
<div className="inline m-l" >
预览 <Switch value={this.state.preview} onChange={this.handlePreviewChange} className="v-middle" inline />
<Button size="sm" className="m-l" onClick={this.clearCache}>清除缓存</Button>
</div>
</Portal>
<Editor preview={this.state.preview} value={this.state.schema} onChange={this.handleChange} className="fix-settings" />
</div>
);
}
}
<Editor
preview={this.state.preview}
value={this.state.schema}
onChange={this.handleChange}
className="fix-settings"
/>
</div>
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +1,99 @@
import React from 'react';
import {
FormItem,
Renderer
} from '../../../src/index';
import {FormItem, Renderer} from '../../../src/index';
@FormItem({
type: 'custom'
type: 'custom'
})
class MyFormItem extends React.Component {
render() {
const {
value,
onChange
} = this.props;
render() {
const {value, onChange} = this.props;
return (
<div>
<p>这个是个自定义组件通过注册渲染器的方式实现</p>
return (
<div>
<p>这个是个自定义组件通过注册渲染器的方式实现</p>
<p>当前值{value}</p>
<p>当前值{value}</p>
<a className="btn btn-default" onClick={() => onChange(Math.round(Math.random() * 10000))}>随机修改</a>
</div>
);
}
<a
className="btn btn-default"
onClick={() => onChange(Math.round(Math.random() * 10000))}
>
随机修改
</a>
</div>
);
}
}
@Renderer({
test: /(^|\/)my\-renderer$/,
test: /(^|\/)my\-renderer$/
})
class CustomRenderer extends React.Component {
render() {
const {tip} = this.props;
return (
<div>{tip || '非 FormItem 类型的渲染器注册, 这种不能修改 form'}</div>
);
}
render() {
const {tip} = this.props;
return (
<div>{tip || '非 FormItem 类型的渲染器注册, 这种不能修改 form'}</div>
);
}
}
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "自定义组件示例",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '自定义组件示例',
body: [
{
type: 'form',
mode: 'horizontal',
api: '/api/mock2/form/saveForm?waitSeconds=2',
actions: [
{
type: "form",
mode: "horizontal",
api: "/api/mock2/form/saveForm?waitSeconds=2",
actions: [
{
type: "submit",
label: "提交",
primary: true
}
],
controls: [
{
name: 'a',
children: ({value, onChange}) => (
<div>
<p>这个是个自定义组件最简单直接的方式不用注册直接使用</p>
<p>当前值{value}</p>
<a className="btn btn-default" onClick={() => onChange(Math.round(Math.random() * 10000))}>随机修改</a>
</div>
)
},
{
type: 'divider'
},
{
name: 'b',
type: 'custom',
label: '自定义FormItem'
},
{
type: 'divider'
},
{
type: 'my-renderer'
}
]
type: 'submit',
label: '提交',
primary: true
}
],
controls: [
{
name: 'a',
children: ({value, onChange}) => (
<div>
<p>这个是个自定义组件最简单直接的方式不用注册直接使用</p>
<p>当前值{value}</p>
<a
className="btn btn-default"
onClick={() => onChange(Math.round(Math.random() * 10000))}
>
随机修改
</a>
</div>
)
},
{
type: 'my-renderer',
tip: '他能放 controls 里面,也能放外面。'
type: 'divider'
},
{
name: 'b',
type: 'custom',
label: '自定义FormItem'
},
{
type: 'divider'
},
{
type: 'my-renderer'
}
]
]
},
{
type: 'my-renderer',
tip: '他能放 controls 里面,也能放外面。'
}
]
};

View File

@ -1,273 +1,276 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
definitions: {
options: {
type: 'combo',
multiple: true,
multiLine: true,
controls: [
{
type: 'group',
controls: [
{
label: "名称",
name: "label",
type: "text",
required: true
},
{
label: "值",
name: "value",
type: "text",
required: true
},
]
},
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
definitions: {
options: {
type: 'combo',
multiple: true,
multiLine: true,
controls: [
{
type: 'group',
controls: [
{
label: '名称',
name: 'label',
type: 'text',
required: true
},
{
$ref: 'options',
label: "子选项",
name: "children",
addButtonText: '新增子选项'
}
]
{
label: '值',
name: 'value',
type: 'text',
required: true
}
]
},
queryItem: {
type: 'combo',
multiple: true,
multiLine: true,
typeSwitchable: false,
conditions: [
{
label: "条件",
test: "!data.hasOwnProperty('connect')",
scaffold: {},
controls: [
{
type: 'group',
className: 'm-b-none',
controls: [
{
name: 'key',
type: 'text',
placeholder: '字段名',
required: true
},
{
name: 'type',
type: 'select',
value: 0,
options: [
{
label: 'int64',
value: 0
},
{
label: 'double64',
value: 1
},
{
label: 'string',
value: 2
},
{
label: 'version',
value: 3
}
]
},
{
type: 'formula',
name: 'opt',
formula: '""',
condition: '${type}'
},
{
name: 'opt',
type: 'select',
placeholder: '请选择',
required: true,
options: [
{
label: '>',
value: '>',
visibleOn: '~[0,1,3].indexOf(this.type)'
},
{
label: '<',
value: '<',
visibleOn: '~[0,1,3].indexOf(this.type)'
},
{
label: '==',
value: '=='
},
{
label: '>=',
value: '>=',
visibleOn: '~[0,1,3].indexOf(this.type)'
},
{
label: '<=',
value: '<=',
visibleOn: '~[0,1,3].indexOf(this.type)'
},
{
label: 'in',
value: 'in',
},
{
label: 'not in',
value: 'not in',
},
{
label: '!=',
value: '!='
},
]
},
{
name: 'val',
type: 'text',
placeholder: '值',
required: true,
visibleOn: '~[">", "<", ">=", "<=", "==", "!="].indexOf(this.opt)'
},
{
name: 'val',
type: 'array',
required: true,
minLength: 1,
items: {
type: 'text',
placeholder: '值',
required: true,
},
visibleOn: '~["in", "not in"].indexOf(this.opt)'
}
]
}
]
},
{
label: "组合",
test: "data.hasOwnProperty('connect')",
scaffold: {
connect: "&",
exprs: [{}]
},
controls: [
{
type: "button-group",
name: 'connect',
value: '&',
clearable: false,
size: 'xs',
options: [
{
label: 'AND',
value: '&'
},
{
label: 'OR',
value: '|'
}
]
},
{
$ref: 'queryItem',
name: 'exprs',
minLength: 1,
value: [{}]
}
]
}
]
},
queryGroup: {
type: 'combo',
multiple: false,
multiLine: true,
controls: [
{
type: "button-group",
name: 'connect',
value: '&',
// label: "",
// mode: 'inline',
clearable: false,
size: 'sm',
options: [
{
label: 'AND',
value: '&'
},
{
label: 'OR',
value: '|'
}
]
},
{
$ref: 'queryItem',
name: 'exprs',
minLength: 1,
value: [{}]
}
]
{
$ref: 'options',
label: '子选项',
name: 'children',
addButtonText: '新增子选项'
}
]
},
type: 'page',
title: '引用',
body: [
'<p>引用可以用来减少重复的结构定义,<code>最主要的是可以用来实现结构的递归定义</code>。</p>',
queryItem: {
type: 'combo',
multiple: true,
multiLine: true,
typeSwitchable: false,
conditions: [
{
type: 'form',
api: '/api/mock/saveForm',
mode: 'horizontal',
controls: [
label: '条件',
test: "!data.hasOwnProperty('connect')",
scaffold: {},
controls: [
{
type: 'group',
className: 'm-b-none',
controls: [
{
$ref: 'options',
name: 'options',
value: [{
label: '选项1',
value: '1'
}],
minLength: 1,
label: '选项配置'
}
]
},
{
type: 'form',
api: '/api/mock/saveForm',
controls: [
{
$ref: 'queryGroup',
name: 'q',
value: {},
label: 'Query'
name: 'key',
type: 'text',
placeholder: '字段名',
required: true
},
{
type: "static",
name: "q",
label: "当前值",
tpl: "<pre>${q|json}</pre>"
name: 'type',
type: 'select',
value: 0,
options: [
{
label: 'int64',
value: 0
},
{
label: 'double64',
value: 1
},
{
label: 'string',
value: 2
},
{
label: 'version',
value: 3
}
]
},
{
type: 'formula',
name: 'opt',
formula: '""',
condition: '${type}'
},
{
name: 'opt',
type: 'select',
placeholder: '请选择',
required: true,
options: [
{
label: '>',
value: '>',
visibleOn: '~[0,1,3].indexOf(this.type)'
},
{
label: '<',
value: '<',
visibleOn: '~[0,1,3].indexOf(this.type)'
},
{
label: '==',
value: '=='
},
{
label: '>=',
value: '>=',
visibleOn: '~[0,1,3].indexOf(this.type)'
},
{
label: '<=',
value: '<=',
visibleOn: '~[0,1,3].indexOf(this.type)'
},
{
label: 'in',
value: 'in'
},
{
label: 'not in',
value: 'not in'
},
{
label: '!=',
value: '!='
}
]
},
{
name: 'val',
type: 'text',
placeholder: '值',
required: true,
visibleOn:
'~[">", "<", ">=", "<=", "==", "!="].indexOf(this.opt)'
},
{
name: 'val',
type: 'array',
required: true,
minLength: 1,
items: {
type: 'text',
placeholder: '值',
required: true
},
visibleOn: '~["in", "not in"].indexOf(this.opt)'
}
]
]
}
]
},
]
{
label: '组合',
test: "data.hasOwnProperty('connect')",
scaffold: {
connect: '&',
exprs: [{}]
},
controls: [
{
type: 'button-group',
name: 'connect',
value: '&',
clearable: false,
size: 'xs',
options: [
{
label: 'AND',
value: '&'
},
{
label: 'OR',
value: '|'
}
]
},
{
$ref: 'queryItem',
name: 'exprs',
minLength: 1,
value: [{}]
}
]
}
]
},
queryGroup: {
type: 'combo',
multiple: false,
multiLine: true,
controls: [
{
type: 'button-group',
name: 'connect',
value: '&',
// label: "",
// mode: 'inline',
clearable: false,
size: 'sm',
options: [
{
label: 'AND',
value: '&'
},
{
label: 'OR',
value: '|'
}
]
},
{
$ref: 'queryItem',
name: 'exprs',
minLength: 1,
value: [{}]
}
]
}
},
type: 'page',
title: '引用',
body: [
'<p>引用可以用来减少重复的结构定义,<code>最主要的是可以用来实现结构的递归定义</code>。</p>',
{
type: 'form',
api: '/api/mock/saveForm',
mode: 'horizontal',
controls: [
{
$ref: 'options',
name: 'options',
value: [
{
label: '选项1',
value: '1'
}
],
minLength: 1,
label: '选项配置'
}
]
},
{
type: 'form',
api: '/api/mock/saveForm',
controls: [
{
$ref: 'queryGroup',
name: 'q',
value: {},
label: 'Query'
},
{
type: 'static',
name: 'q',
label: '当前值',
tpl: '<pre>${q|json}</pre>'
}
]
}
]
};

View File

@ -1,46 +1,47 @@
import React from 'react';
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "Editor",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'Editor',
body: [
{
type: 'form',
api: '/api/mock2/saveForm?waitSeconds=2',
title: '',
controls: [
{
type: "form",
api: "/api/mock2/saveForm?waitSeconds=2",
title: "",
controls: [
{
name: "javascript",
type: "editor",
label: "Javascript",
language: 'javascript',
value: "console.log(1, 2, 3);"
},
name: 'javascript',
type: 'editor',
label: 'Javascript',
language: 'javascript',
value: 'console.log(1, 2, 3);'
},
{
name: "html",
type: "editor",
language: 'html',
label: "Html",
value: "<html><head><title>Hello</title></head><body><p>world</p></body></html>"
},
{
name: 'html',
type: 'editor',
language: 'html',
label: 'Html',
value:
'<html><head><title>Hello</title></head><body><p>world</p></body></html>'
},
{
name: "css",
type: "editor",
language: 'css',
label: "CSS",
value: "body {color: red;}"
},
{
name: 'css',
type: 'editor',
language: 'css',
label: 'CSS',
value: 'body {color: red;}'
},
{
name: "json",
type: "editor",
language: 'json',
label: "JSON",
value: `{"a": 1, "b": 2}`
}
]
{
name: 'json',
type: 'editor',
language: 'json',
label: 'JSON',
value: `{"a": 1, "b": 2}`
}
]
]
}
]
};

View File

@ -1,148 +1,148 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "FieldSet 示例",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'FieldSet 示例',
body: [
{
type: 'form',
mode: 'horizontal',
api: '/api/mock2/saveForm?waitSeconds=2',
actions: [
{
type: "form",
mode: "horizontal",
api: "/api/mock2/saveForm?waitSeconds=2",
actions: [
type: 'submit',
label: '提交',
primary: true
}
],
collapsable: true,
title: 'fieldSet 可以对表单元素做个分组',
controls: [
{
type: 'fieldSet',
title: '基本信息',
collapsable: true,
controls: [
{
type: 'group',
controls: [
{
type: "submit",
label: "提交",
primary: true
}
],
collapsable: true,
title: 'fieldSet 可以对表单元素做个分组',
controls: [
{
type: 'fieldSet',
title: '基本信息',
collapsable: true,
controls: [
{
type: 'group',
controls: [
{
type: "email",
name: "email",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "password",
name: "password",
label: false,
placeholder: "Password"
}
]
},
{
type: "divider"
},
{
type: 'group',
controls: [
{
type: "email",
name: "email",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "checkbox",
name: "rememberMe",
label: false,
option: "Remember me"
}
]
}
]
type: 'email',
name: 'email',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
title: '其他信息',
type: 'fieldSet',
controls: [
{
type: "email",
name: "email",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "divider"
},
{
type: "checkbox",
name: "rememberMe",
option: "记住我"
}
]
type: 'password',
name: 'password',
label: false,
placeholder: 'Password'
}
]
]
},
{
type: 'divider'
},
{
type: 'group',
controls: [
{
type: 'email',
name: 'email',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
type: 'checkbox',
name: 'rememberMe',
label: false,
option: 'Remember me'
}
]
}
]
},
{
title: '其他信息',
type: 'fieldSet',
controls: [
{
type: 'email',
name: 'email',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
type: 'divider'
},
{
type: 'checkbox',
name: 'rememberMe',
option: '记住我'
}
]
}
]
},
{
title: 'FieldSet 样式集',
type: 'form',
controls: [
{
title: '超级小',
type: 'fieldSet',
className: 'fieldset-xs',
controls: [
{
type: 'plain',
text: '文本 ...'
}
]
},
{
title: "FieldSet 样式集",
type: "form",
controls: [
{
title: "超级小",
type: 'fieldSet',
className: "fieldset-xs",
controls: [
{
type: "plain",
text: "文本 ..."
}
]
},
{
title: "小尺寸",
type: 'fieldSet',
className: "fieldset-sm",
controls: [
{
type: "plain",
text: "文本 ..."
}
]
},
{
title: "正常尺寸",
type: 'fieldSet',
className: "fieldset",
controls: [
{
type: "plain",
text: "文本 ..."
}
]
},
{
title: "中大尺寸",
type: 'fieldSet',
className: "fieldset-md",
controls: [
{
type: "plain",
text: "文本 ..."
}
]
},
{
title: "超大尺寸",
type: 'fieldSet',
className: "fieldset-lg",
controls: [
{
type: "plain",
text: "文本 ..."
}
]
}
]
title: '小尺寸',
type: 'fieldSet',
className: 'fieldset-sm',
controls: [
{
type: 'plain',
text: '文本 ...'
}
]
},
{
title: '正常尺寸',
type: 'fieldSet',
className: 'fieldset',
controls: [
{
type: 'plain',
text: '文本 ...'
}
]
},
{
title: '中大尺寸',
type: 'fieldSet',
className: 'fieldset-md',
controls: [
{
type: 'plain',
text: '文本 ...'
}
]
},
{
title: '超大尺寸',
type: 'fieldSet',
className: 'fieldset-lg',
controls: [
{
type: 'plain',
text: '文本 ...'
}
]
}
]
]
}
]
};

View File

@ -1,101 +1,101 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "FieldSet In Tabs",
remark: "",
body: {
type: "form",
collapsable: true,
tabs: [
{
title: "Tab A",
fieldSet: [
{
title: "Group A",
tabs: [
{
title: "SubTab A",
controls: [
{
name: "a",
type: "text",
label: "Text"
},
{
name: "a",
type: "text",
label: "Text"
}
]
},
{
title: "SubTab B",
controls: [
{
name: "a",
type: "text",
label: "Text"
},
{
name: "a",
type: "text",
label: "Text"
}
]
}
]
},
{
title: "Group B",
controls: [
{
name: "a",
type: "text",
label: "Text"
},
{
name: "a",
type: "text",
label: "Text"
}
]
}
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'FieldSet In Tabs',
remark: '',
body: {
type: 'form',
collapsable: true,
tabs: [
{
title: 'Tab A',
fieldSet: [
{
title: 'Group A',
tabs: [
{
title: 'SubTab A',
controls: [
{
name: 'a',
type: 'text',
label: 'Text'
},
{
name: 'a',
type: 'text',
label: 'Text'
}
]
},
{
title: "Tab B",
fieldSet: [
{
title: "Group A",
controls: [
{
name: "a",
type: "text",
label: "Text"
},
{
name: "a",
type: "text",
label: "Text"
}
]
},
{
title: "Group B",
controls: [
{
name: "a",
type: "text",
label: "Text"
},
{
name: "a",
type: "text",
label: "Text"
}
]
}
},
{
title: 'SubTab B',
controls: [
{
name: 'a',
type: 'text',
label: 'Text'
},
{
name: 'a',
type: 'text',
label: 'Text'
}
]
}
}
]
},
{
title: 'Group B',
controls: [
{
name: 'a',
type: 'text',
label: 'Text'
},
{
name: 'a',
type: 'text',
label: 'Text'
}
]
}
]
}
},
{
title: 'Tab B',
fieldSet: [
{
title: 'Group A',
controls: [
{
name: 'a',
type: 'text',
label: 'Text'
},
{
name: 'a',
type: 'text',
label: 'Text'
}
]
},
{
title: 'Group B',
controls: [
{
name: 'a',
type: 'text',
label: 'Text'
},
{
name: 'a',
type: 'text',
label: 'Text'
}
]
}
]
}
]
}
};

View File

@ -1,127 +1,127 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "公式示例",
"body": [
"<p>通过公式,可以动态的设置目标值。</p>",
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '公式示例',
body: [
'<p>通过公式,可以动态的设置目标值。</p>',
{
type: 'form',
title: '自动应用',
api: '/api/mock2/form/saveForm',
controls: [
{
"type": "form",
title: "自动应用",
"api": "/api/mock2/form/saveForm",
"controls": [
{
"type": "number",
"name": "a",
"label": "A"
},
{
"type": "number",
"name": "b",
"label": "B"
},
{
"type": "number",
"name": "sum",
"label": "和",
"disabled": true,
description: '自动计算 A + B'
},
{
"type": "formula",
"name": "sum",
"value": 0,
"formula": "a + b"
}
]
type: 'number',
name: 'a',
label: 'A'
},
{
"type": "form",
title: "手动应用",
"api": "/api/mock2/form/saveForm",
"controls": [
{
"type": "number",
"name": "a",
"label": "A"
},
type: 'number',
name: 'b',
label: 'B'
},
{
"type": "number",
"name": "b",
"label": "B"
},
{
type: 'number',
name: 'sum',
label: '和',
disabled: true,
description: '自动计算 A + B'
},
{
type: "group",
controls: [
{
"type": "number",
"name": "sum",
"label": "和",
"disabled": true,
"columnClassName": "col-sm-11",
},
{
type: 'formula',
name: 'sum',
value: 0,
formula: 'a + b'
}
]
},
{
"type": "button",
"label": "计算",
"columnClassName": "col-sm-1 v-bottom",
"target": "theFormula"
}
]
},
{
type: 'form',
title: '手动应用',
api: '/api/mock2/form/saveForm',
controls: [
{
type: 'number',
name: 'a',
label: 'A'
},
{
"type": "formula",
"name": "sum",
"id": "theFormula",
"value": 0,
"formula": "a + b",
"initSet": false,
"autoSet": false
}
]
{
type: 'number',
name: 'b',
label: 'B'
},
{
type: 'group',
controls: [
{
type: 'number',
name: 'sum',
label: '和',
disabled: true,
columnClassName: 'col-sm-11'
},
{
type: 'button',
label: '计算',
columnClassName: 'col-sm-1 v-bottom',
target: 'theFormula'
}
]
},
{
type: 'formula',
name: 'sum',
id: 'theFormula',
value: 0,
formula: 'a + b',
initSet: false,
autoSet: false
}
]
},
{
type: 'form',
title: '条件应用',
api: '/api/mock2/form/saveForm',
controls: [
{
type: 'radios',
name: 'radios',
inline: true,
label: 'radios',
options: [
{
label: 'a',
value: 'a'
},
{
label: 'b',
value: 'b'
}
],
description: 'radios 变化会自动清空 B'
},
{
"type": "form",
title: "条件应用",
"api": "/api/mock2/form/saveForm",
"controls": [
{
"type": "radios",
"name": "radios",
"inline": true,
"label": "radios",
"options": [
{
"label": 'a',
"value": 'a'
},
{
"label": 'b',
"value": 'b'
},
],
"description": 'radios 变化会自动清空 B'
},
{
"type": "text",
"name": "b",
"label": "B"
},
{
"type": "formula",
"name": "b",
"value": 'some string',
"formula": "''",
"condition": '${radios}',
"initSet": false,
}
]
type: 'text',
name: 'b',
label: 'B'
},
]
}
{
type: 'formula',
name: 'b',
value: 'some string',
formula: "''",
condition: '${radios}',
initSet: false
}
]
}
]
};

File diff suppressed because it is too large Load Diff

View File

@ -1,96 +1,92 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "其他类型演示",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '其他类型演示',
body: [
{
type: 'form',
api: '/api/mock2/saveForm?waitSeconds=2',
title: 'Hint demo',
mode: 'horizontal',
horizontal: {
leftFixed: true
},
controls: [
{
type: "form",
api: "/api/mock2/saveForm?waitSeconds=2",
title: "Hint demo",
mode: "horizontal",
horizontal: {
leftFixed: true
name: 'button',
type: 'button',
label: 'ID',
value: '',
size: 'xs',
hint: '比如输入 a-xxxx-xxx'
},
{
type: 'input-group',
size: 'md',
label: 'Icon 组合',
controls: [
{
type: 'icon',
addOnclassName: 'no-bg',
className: 'text-sm',
icon: 'search',
vendor: 'iconfont'
},
controls: [
{
name: "button",
type: "button",
label: "ID",
value: "",
size: 'xs',
hint: '比如输入 a-xxxx-xxx'
},
{
type: 'text',
placeholder: '搜索作业ID/名称',
inputClassName: 'b-l-none p-l-none',
name: 'jobName'
}
]
},
{
"type": "input-group",
"size": "md",
"label": "Icon 组合",
"controls": [
{
"type": "icon",
"addOnclassName": "no-bg",
className: "text-sm",
"icon": "search",
"vendor": "iconfont"
},
{
"type": "text",
"placeholder": "搜索作业ID/名称",
"inputClassName": "b-l-none p-l-none",
"name": "jobName"
}
]
},
{
name: 'a',
type: 'text',
label: 'ID',
value: '',
size: 'xs',
hint: '比如输入 a-xxxx-xxx'
},
{
name: "a",
type: "text",
label: "ID",
value: "",
size: 'xs',
hint: '比如输入 a-xxxx-xxx'
},
{
name: 'b',
type: 'text',
label: 'ID',
value: '',
size: 'sm',
hint: '比如输入 a-xxxx-xxx'
},
{
name: "b",
type: "text",
label: "ID",
value: "",
size: 'sm',
hint: '比如输入 a-xxxx-xxx'
},
{
name: 'c',
type: 'text',
label: 'ID',
value: '',
size: 'md',
hint: '比如输入 a-xxxx-xxx'
},
{
name: "c",
type: "text",
label: "ID",
value: "",
size: 'md',
hint: '比如输入 a-xxxx-xxx'
},
{
name: 'd',
type: 'text',
label: 'ID',
value: '',
size: 'lg',
hint: '比如输入 a-xxxx-xxx'
},
{
name: "d",
type: "text",
label: "ID",
value: "",
size: 'lg',
hint: '比如输入 a-xxxx-xxx'
},
{
name: "tag",
type: "tag",
label: "Tag",
size: 'md',
clearable: true,
placeholder: "多个标签以逗号分隔",
options: [
"周小度",
"杜小度"
]
}
]
{
name: 'tag',
type: 'tag',
label: 'Tag',
size: 'md',
clearable: true,
placeholder: '多个标签以逗号分隔',
options: ['周小度', '杜小度']
}
]
]
}
]
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,93 +1,93 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "显隐切换示例",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '显隐切换示例',
body: [
{
name: 'hiddenOn',
type: 'form',
mode: 'horizontal',
api: '/api/mock2/saveForm?waitSeconds=2',
title: 'Hide On 和 disabledOn 示例',
controls: [
{
name: "hiddenOn",
type: "form",
mode: "horizontal",
api: "/api/mock2/saveForm?waitSeconds=2",
title: "Hide On 和 disabledOn 示例",
controls: [
{
type: "radios",
name: "type",
label: "类型选择",
inline: true,
value: "1",
options: [
{
label: "类型 1",
value: "1"
},
{
label: "类型 2",
value: "2"
},
{
label: "类型 3",
value: "3"
}
],
description: '<span class="text-danger">请切换类型来看效果</span>'
},
{
type: "text",
label: "所有可见",
name: "text1"
},
{
type: "text",
label: "类型2 可见",
hiddenOn: "data.type != 2",
name: "text2"
},
{
type: "text",
label: "类型3 不可点",
disabledOn: "data.type == 3",
name: "text3"
},
{
type: "text",
required: true,
label: "必填字段",
name: "test4"
},
{
type: "button-toolbar",
buttons: [
{
type: "submit",
disabledOn: "data.type == 1",
label: "类型1不可点"
},
{
type: "reset",
label: "类型3出现且不可点",
visibleOn: "data.type == 3",
disabledOn: "data.type == 3",
},
{
type: "button",
label: "Baidu",
href: "http://www.baidu.com?a=1&b=$test4"
},
{
type: "button",
actionType: "ajax",
label: "No Submit",
action: "/api/mock2/saveForm?waitSeconds=5"
},
{
type: "submit",
actionType: "ajax",
label: "Submit",
action: "/api/mock2/saveForm?waitSeconds=5"
}
]
}
]
type: 'radios',
name: 'type',
label: '类型选择',
inline: true,
value: '1',
options: [
{
label: '类型 1',
value: '1'
},
{
label: '类型 2',
value: '2'
},
{
label: '类型 3',
value: '3'
}
],
description: '<span class="text-danger">请切换类型来看效果</span>'
},
{
type: 'text',
label: '所有可见',
name: 'text1'
},
{
type: 'text',
label: '类型2 可见',
hiddenOn: 'data.type != 2',
name: 'text2'
},
{
type: 'text',
label: '类型3 不可点',
disabledOn: 'data.type == 3',
name: 'text3'
},
{
type: 'text',
required: true,
label: '必填字段',
name: 'test4'
},
{
type: 'button-toolbar',
buttons: [
{
type: 'submit',
disabledOn: 'data.type == 1',
label: '类型1不可点'
},
{
type: 'reset',
label: '类型3出现且不可点',
visibleOn: 'data.type == 3',
disabledOn: 'data.type == 3'
},
{
type: 'button',
label: 'Baidu',
href: 'http://www.baidu.com?a=1&b=$test4'
},
{
type: 'button',
actionType: 'ajax',
label: 'No Submit',
action: '/api/mock2/saveForm?waitSeconds=5'
},
{
type: 'submit',
actionType: 'ajax',
label: 'Submit',
action: '/api/mock2/saveForm?waitSeconds=5'
}
]
}
]
]
}
]
};

View File

@ -1,90 +1,91 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "动态拉取选项",
name: "page-form-remote",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '动态拉取选项',
name: 'page-form-remote',
body: [
{
type: 'form',
title: '动态表单元素示例',
name: 'demo-form',
api: '/api/mock2/form/saveForm?waitSeconds=2',
mode: 'horizontal',
actions: [
{
type: "form",
title: "动态表单元素示例",
name: "demo-form",
api: "/api/mock2/form/saveForm?waitSeconds=2",
mode: "horizontal",
actions: [
{
type: "submit",
label: "提交"
}
],
controls: [
{
name: "select",
type: "select",
label: "动态选项",
source: "/api/mock2/form/getOptions?waitSeconds=1",
description: '通过接口一口气拉取选项',
clearable: true,
searchable: true
},
{
type: "divider"
},
{
name: "select2",
type: "select",
label: "选项自动补全",
autoComplete: "/api/mock2/options/autoComplete?term=$term",
placeholder: "请输入",
description: '通过接口自动补全'
},
{
type: "divider"
},
{
type: "text",
name: "text",
label: "文本提示",
source: "/api/mock2/form/getOptions?waitSeconds=1",
placeholder: '请选择'
},
{
type: "divider"
},
{
name: "text2",
type: "text",
label: "文本自动补全",
clearable: true,
autoComplete: "/api/mock2/options/autoComplete2?term=$term",
description: '通过接口自动补全'
},
{
name: "chained",
type: "chained-select",
label: "级联选项",
source:
"/api/mock2/options/chainedOptions?waitSeconds=1&parentId=$parentId&level=$level&maxLevel=4&waiSeconds=1",
desc: "无限级别, 只要 api 返回数据就能继续往下选择. 当没有下级时请返回 null.",
value: "a,b"
},
{
type: "divider"
},
{
name: "tree",
type: "tree",
label: "动态树",
source: "/api/mock2/options/tree?waitSeconds=1"
},
{
type: "divider"
},
{
name: "matrix",
type: "matrix",
label: "动态矩阵开关",
source: "/api/mock2/options/matrix?waitSeconds=1"
}
]
type: 'submit',
label: '提交'
}
]
],
controls: [
{
name: 'select',
type: 'select',
label: '动态选项',
source: '/api/mock2/form/getOptions?waitSeconds=1',
description: '通过接口一口气拉取选项',
clearable: true,
searchable: true
},
{
type: 'divider'
},
{
name: 'select2',
type: 'select',
label: '选项自动补全',
autoComplete: '/api/mock2/options/autoComplete?term=$term',
placeholder: '请输入',
description: '通过接口自动补全'
},
{
type: 'divider'
},
{
type: 'text',
name: 'text',
label: '文本提示',
source: '/api/mock2/form/getOptions?waitSeconds=1',
placeholder: '请选择'
},
{
type: 'divider'
},
{
name: 'text2',
type: 'text',
label: '文本自动补全',
clearable: true,
autoComplete: '/api/mock2/options/autoComplete2?term=$term',
description: '通过接口自动补全'
},
{
name: 'chained',
type: 'chained-select',
label: '级联选项',
source:
'/api/mock2/options/chainedOptions?waitSeconds=1&parentId=$parentId&level=$level&maxLevel=4&waiSeconds=1',
desc:
'无限级别, 只要 api 返回数据就能继续往下选择. 当没有下级时请返回 null.',
value: 'a,b'
},
{
type: 'divider'
},
{
name: 'tree',
type: 'tree',
label: '动态树',
source: '/api/mock2/options/tree?waitSeconds=1'
},
{
type: 'divider'
},
{
name: 'matrix',
type: 'matrix',
label: '动态矩阵开关',
source: '/api/mock2/options/matrix?waitSeconds=1'
}
]
}
]
};

View File

@ -1,21 +1,21 @@
import React from 'react';
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "富文本编辑器",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '富文本编辑器',
body: [
{
type: 'form',
api: '/api/mock2/saveForm?waitSeconds=2',
title: 'Form elements',
controls: [
{
type: "form",
api: "/api/mock2/saveForm?waitSeconds=2",
title: "Form elements",
controls: [
{
name: "html",
type: "rich-text",
label: "富文本",
value: "<p>Just do <code>IT</code></p>"
}
]
name: 'html',
type: 'rich-text',
label: '富文本',
value: '<p>Just do <code>IT</code></p>'
}
]
]
}
]
};

View File

@ -3,154 +3,157 @@ import TitleBar from '../../../src/components/TitleBar';
import {render} from '../../../src/index';
const Schema = {
"title": "Person",
"type": "object",
"properties": {
"firstName": {
"title": "First Name",
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
},
"tag": {
"type": "array",
"description": "Tags",
"default": ["IT"],
"items": {
"type": "text"
}
},
"clients": {
"type": "array",
"description": "Tags",
"items": {
"type": "object",
"properties": {
"firstName": {
"title": "First Name",
"type": "string"
},
"lastName": {
"type": "string"
}
}
}
}
title: 'Person',
type: 'object',
properties: {
firstName: {
title: 'First Name',
type: 'string'
},
"required": ["firstName", "lastName"]
lastName: {
type: 'string'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
tag: {
type: 'array',
description: 'Tags',
default: ['IT'],
items: {
type: 'text'
}
},
clients: {
type: 'array',
description: 'Tags',
items: {
type: 'object',
properties: {
firstName: {
title: 'First Name',
type: 'string'
},
lastName: {
type: 'string'
}
}
}
}
},
required: ['firstName', 'lastName']
};
function property2control(property, key, schema) {
const requiredList= schema.required || [];
const rest = {};
const validations = {};
let type = 'text';
const requiredList = schema.required || [];
const rest = {};
const validations = {};
let type = 'text';
if (property.type === 'integer') {
type = 'number';
typeof property.minimum === 'number' && (rest.min = property.minimum);
// property.max
} else if (property.type === 'array') {
type = 'combo';
const items = property.items;
if (property.type === 'integer') {
type = 'number';
typeof property.minimum === 'number' && (rest.min = property.minimum);
// property.max
} else if (property.type === 'array') {
type = 'combo';
const items = property.items;
if (items.type === 'object') {
rest.controls = makeControls(items.properties, items);
rest.multiLine = true;
} else {
type = 'array';
rest.inline = true;
rest.items = property2control(items, 'item', property);
}
if (items.type === 'object') {
rest.controls = makeControls(items.properties, items);
rest.multiLine = true;
} else {
type = 'array';
rest.inline = true;
rest.items = property2control(items, 'item', property);
}
}
if (typeof property.minimum === 'number') {
validations.minimum = property.minimum;
}
if (typeof property.minimum === 'number') {
validations.minimum = property.minimum;
}
return {
name: key,
type,
required: !!~requiredList.indexOf(key),
label: property.title || property.description,
desc: property.title && property.description,
value: property.default,
validations,
...rest
};
return {
name: key,
type,
required: !!~requiredList.indexOf(key),
label: property.title || property.description,
desc: property.title && property.description,
value: property.default,
validations,
...rest
};
}
function makeControls(properties, schema) {
const keys = Object.keys(properties);
return keys.map(key => property2control(properties[key], key, schema));
const keys = Object.keys(properties);
return keys.map(key => property2control(properties[key], key, schema));
}
function JSONSchme2AMisSchema(schema) {
if (schema.type !== 'object') {
throw new Error('JSONSchme2AMisSchema 只支持 object 转换');
}
if (schema.type !== 'object') {
throw new Error('JSONSchme2AMisSchema 只支持 object 转换');
}
return {
title: schema.title,
type: 'form',
mode: "horizontal",
controls: makeControls(schema.properties, schema)
}
return {
title: schema.title,
type: 'form',
mode: 'horizontal',
controls: makeControls(schema.properties, schema)
};
}
const amisFormSchema = JSONSchme2AMisSchema(Schema);
export default class JSONSchemaForm extends React.Component {
state = {
data: {}
};
state = {
data: {}
};
renderForm() {
return render({
type: 'page',
title: '',
body: {
...amisFormSchema,
onChange: values => this.setState({
data: {
...values
}
})
renderForm() {
return render({
type: 'page',
title: '',
body: {
...amisFormSchema,
onChange: values =>
this.setState({
data: {
...values
}
});
}
})
}
});
}
render() {
return (
<div>
<TitleBar title="JSON Schema Form" />
<div className="wrapper">
<div>
<h3>Schema</h3>
<pre><code>{JSON.stringify(Schema, null, 2)}</code></pre>
</div>
render() {
return (
<div>
<TitleBar title="JSON Schema Form" />
<div className="wrapper">
<div>
<h3>Schema</h3>
<pre>
<code>{JSON.stringify(Schema, null, 2)}</code>
</pre>
</div>
<div>
<h3>Form</h3>
{this.renderForm()}
</div>
<div>
<h3>Form</h3>
{this.renderForm()}
</div>
<div>
<h3>Data</h3>
<pre><code>{JSON.stringify(this.state.data, null, 2)}</code></pre>
</div>
</div>
</div>
);
}
<div>
<h3>Data</h3>
<pre>
<code>{JSON.stringify(this.state.data, null, 2)}</code>
</pre>
</div>
</div>
</div>
);
}
}

View File

@ -1,130 +1,132 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "所有 Form 元素列举",
data: {
id: 1,
image: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg"
},
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '所有 Form 元素列举',
data: {
id: 1,
image:
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg'
},
body: [
{
type: 'form',
api: '/api/mock2/saveForm?waitSeconds=2',
title: '表单项静态展示',
mode: 'horizontal',
controls: [
{
type: "form",
api: "/api/mock2/saveForm?waitSeconds=2",
title: "表单项静态展示",
mode: "horizontal",
controls: [
{
type: "static",
label: "文本",
value: "文本"
},
type: 'static',
label: '文本',
value: '文本'
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: "static-tpl",
label: "模板",
tpl: "自己拼接 HTML 取变量 \\${id}: ${id}"
},
{
type: 'static-tpl',
label: '模板',
tpl: '自己拼接 HTML 取变量 \\${id}: ${id}'
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: "static-date",
label: "日期",
value: Math.round(Date.now()/1000)
},
{
type: 'static-date',
label: '日期',
value: Math.round(Date.now() / 1000)
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: "static-datetime",
label: "日期时间",
value: Math.round(Date.now()/1000)
},
{
type: 'static-datetime',
label: '日期时间',
value: Math.round(Date.now() / 1000)
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: "static-mapping",
label: "映射",
value: Math.floor(Math.random() * 5),
map: {
'*': "<span class='label label-default'>-</span>",
'0': "<span class='label label-info'>一</span>",
'1': "<span class='label label-success'>二</span>",
'2': "<span class='label label-danger'>三</span>",
'3': "<span class='label label-warning'>四</span>",
'4': "<span class='label label-primary'>五</span>",
}
},
{
type: 'static-mapping',
label: '映射',
value: Math.floor(Math.random() * 5),
map: {
'*': "<span class='label label-default'>-</span>",
'0': "<span class='label label-info'>一</span>",
'1': "<span class='label label-success'>二</span>",
'2': "<span class='label label-danger'>三</span>",
'3': "<span class='label label-warning'>四</span>",
'4': "<span class='label label-primary'>五</span>"
}
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: "static-progress",
label: "进度",
value: 66.66
},
{
type: 'static-progress',
label: '进度',
value: 66.66
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: "static-image",
label: "图片",
name: "image",
popOver: {
title: "查看大图",
body: '<div class="w-xxl"><img class="w-full" src="${image}"/></div>'
}
},
{
type: 'static-image',
label: '图片',
name: 'image',
popOver: {
title: '查看大图',
body:
'<div class="w-xxl"><img class="w-full" src="${image}"/></div>'
}
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: 'static-json',
label: 'JSON',
value: {a: 1, b: 2, c: {d: 3}}
},
{
type: 'static-json',
label: 'JSON',
value: {a: 1, b: 2, c: {d: 3}}
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: "static",
label: "可复制",
value: "文本",
copyable: {
content: "内容,支持变量 ${id}"
}
},
{
type: 'static',
label: '可复制',
value: '文本',
copyable: {
content: '内容,支持变量 ${id}'
}
},
{
type: 'divider'
},
{
type: 'divider'
},
{
type: "static",
name: "text",
label: "可快速编辑",
value: "文本",
quickEdit: true
},
]
{
type: 'static',
name: 'text',
label: '可快速编辑',
value: '文本',
quickEdit: true
}
]
]
}
]
};

View File

@ -1,60 +1,60 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "SubForm 示例",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'SubForm 示例',
body: [
{
type: 'form',
api: '/api/mock2/saveForm?waitSeconds=2',
title: 'Form elements',
mode: 'horizontal',
// debug: true,
controls: [
{
type: "form",
api: "/api/mock2/saveForm?waitSeconds=2",
title: "Form elements",
mode: "horizontal",
// debug: true,
type: 'form',
label: '子表单单条',
name: 'subForm1',
btnLabel: '点击设置',
form: {
title: '子表单',
controls: [
{
type: "form",
label: "子表单单条",
name: "subForm1",
btnLabel: "点击设置",
form: {
title: "子表单",
controls: [
{
name: "a",
type: "text",
label: "Foo"
},
{
name: "b",
type: "switch",
label: "Boo"
}
]
}
},
{
type: "form",
label: "子表单多条",
name: "subForm2",
labelField: 'a',
btnLabel: "点击设置",
multiple: true,
form: {
title: "子表单",
controls: [
{
name: "a",
type: "text",
label: "Foo"
},
{
name: "b",
type: "switch",
label: "Boo"
}
]
}
},
{
name: 'a',
type: 'text',
label: 'Foo'
},
{
name: 'b',
type: 'switch',
label: 'Boo'
}
]
}
},
{
type: 'form',
label: '子表单多条',
name: 'subForm2',
labelField: 'a',
btnLabel: '点击设置',
multiple: true,
form: {
title: '子表单',
controls: [
{
name: 'a',
type: 'text',
label: 'Foo'
},
{
name: 'b',
type: 'switch',
label: 'Boo'
}
]
}
}
]
]
}
]
};

View File

@ -1,146 +1,146 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "表格编辑",
body: {
type: "form",
mode: "horizontal",
api: "/api/mock2/form/saveForm?waitSeconds=2",
actions: [
{
type: "submit",
label: "提交",
primary: true
}
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '表格编辑',
body: {
type: 'form',
mode: 'horizontal',
api: '/api/mock2/form/saveForm?waitSeconds=2',
actions: [
{
type: 'submit',
label: '提交',
primary: true
}
],
controls: [
{
type: 'combo',
name: 'colors',
label: 'Combo',
multiple: true,
draggable: true,
multiLine: true,
value: [
{
color: 'green',
name: '颜色'
}
],
controls: [
{
type: 'combo',
name: 'colors',
label: 'Combo',
multiple: true,
draggable: true,
multiLine: true,
value: [
{
color: 'green',
name: '颜色'
}
],
controls: [
{
type: 'color',
name: 'color'
},
{
type: 'text',
name: 'name',
placeholder: '说明文字'
}
]
},
{
type: "static",
label: "当前值",
tpl: "<pre>${colors|json}</pre>"
},
{
type: 'table',
name: 'colors',
label: 'Table',
draggable: true,
columns: [
{
label: 'Color',
name: 'color',
quickEdit: {
type: 'color',
saveImmediately: true
}
},
{
label: '说明文字',
name: 'name',
quickEdit: {
type: 'text',
mode: 'inline',
saveImmediately: true
}
}
]
},
{
type: 'button',
label: 'Table2新增一行',
target: 'table2',
actionType: 'add'
},
{
"type": "table",
"name": "table2",
"label": "Table2",
"editable": true,
"addable": true,
"removable": true,
"draggable": true,
"columns": [
{
"name": "a",
"label": "A"
},
{
"name": "b",
"label": "B",
"quickEdit": {
"type": "select",
"options": [
{
"label": "A",
"value": "a"
},
{
"label": "B",
"value": "b"
}
]
}
}
]
},
{
"type": "table",
"name": "table3",
"label": "Table3(指定第2列只有update时能编辑)",
"editable": true,
"addable": true,
"removable": true,
"draggable": true,
"columns": [
{
"name": "a",
"label": "A",
"quickEdit": true
},
{
"name": "b",
"label": "B",
"quickEdit": false,
"quickEditOnUpdate": {
"type": "select",
"options": [
{
"label": "A",
"value": "a"
},
{
"label": "B",
"value": "b"
}
]
},
}
]
}
{
type: 'color',
name: 'color'
},
{
type: 'text',
name: 'name',
placeholder: '说明文字'
}
]
}
},
{
type: 'static',
label: '当前值',
tpl: '<pre>${colors|json}</pre>'
},
{
type: 'table',
name: 'colors',
label: 'Table',
draggable: true,
columns: [
{
label: 'Color',
name: 'color',
quickEdit: {
type: 'color',
saveImmediately: true
}
},
{
label: '说明文字',
name: 'name',
quickEdit: {
type: 'text',
mode: 'inline',
saveImmediately: true
}
}
]
},
{
type: 'button',
label: 'Table2新增一行',
target: 'table2',
actionType: 'add'
},
{
type: 'table',
name: 'table2',
label: 'Table2',
editable: true,
addable: true,
removable: true,
draggable: true,
columns: [
{
name: 'a',
label: 'A'
},
{
name: 'b',
label: 'B',
quickEdit: {
type: 'select',
options: [
{
label: 'A',
value: 'a'
},
{
label: 'B',
value: 'b'
}
]
}
}
]
},
{
type: 'table',
name: 'table3',
label: 'Table3(指定第2列只有update时能编辑)',
editable: true,
addable: true,
removable: true,
draggable: true,
columns: [
{
name: 'a',
label: 'A',
quickEdit: true
},
{
name: 'b',
label: 'B',
quickEdit: false,
quickEditOnUpdate: {
type: 'select',
options: [
{
label: 'A',
value: 'a'
},
{
label: 'B',
value: 'b'
}
]
}
}
]
}
]
}
};

View File

@ -1,169 +1,171 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "Tabs 示例",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'Tabs 示例',
body: [
{
type: 'form',
mode: 'horizontal',
api: '/api/mock2/form/saveForm?waitSeconds=2',
title: '',
actions: [
{
type: "form",
mode: "horizontal",
api: "/api/mock2/form/saveForm?waitSeconds=2",
title: "",
actions: [
type: 'button',
actionType: 'dialog',
label: '弹框中的 Tabs',
level: 'info',
dialog: {
title: '',
// size: "md",
body: {
type: 'form',
mode: 'horizontal',
horizontal: {
leftFixed: 'xs'
},
api: '/api/mock2/form/saveForm?waitSeconds=2',
actions: [
{
type: "button",
actionType: "dialog",
label: "弹框中的 Tabs",
level: "info",
dialog: {
title: "",
// size: "md",
body: {
type: "form",
mode: "horizontal",
horizontal: {
leftFixed: 'xs'
},
api: "/api/mock2/form/saveForm?waitSeconds=2",
actions: [
{
type: "submit",
label: "提交",
primary: true
}
],
controls: [{
type: 'tabs',
tabs: [
{
title: "基本信息",
controls: [
[
{
type: "email",
name: "email1",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "password",
name: "password",
placeholder: "密码",
label: false
}
],
{
type: "divider"
},
[
{
type: "email",
name: "email2",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "checkbox",
name: "rememberMe",
label: false,
option: "记住我"
}
]
]
},
{
title: "其他信息",
controls: [
{
type: "email",
name: "email3",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "divider"
},
{
type: "checkbox",
name: "rememberMe2",
option: "记住我"
}
]
}
]
}]
}
}
},
{
type: "submit",
label: "提交",
primary: true
type: 'submit',
label: '提交',
primary: true
}
],
controls: [
],
controls: [
{
type: 'tabs',
tabs: [
type: 'tabs',
tabs: [
{
title: '基本信息',
controls: [
[
{
type: 'email',
name: 'email1',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
type: 'password',
name: 'password',
placeholder: '密码',
label: false
}
],
{
title: "基本信息",
hash: 'tab1',
controls: [
[
{
type: "email",
name: "email",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "password",
name: "password",
placeholder: "密码",
label: false
}
],
{
type: "divider"
},
[
{
type: "email",
name: "email2",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "checkbox",
name: "rememberMe",
label: false,
option: "记住我"
}
]
]
type: 'divider'
},
[
{
type: 'email',
name: 'email2',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
type: 'checkbox',
name: 'rememberMe',
label: false,
option: '记住我'
}
]
]
},
{
title: '其他信息',
controls: [
{
type: 'email',
name: 'email3',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
title: "其他信息",
hash: 'tab2',
controls: [
{
type: "email",
name: "email3",
placeholder: "请输入邮箱地址",
label: "邮箱"
},
{
type: "divider"
},
{
type: "checkbox",
name: "rememberMe4",
label: "记住我"
}
]
type: 'divider'
},
{
type: 'checkbox',
name: 'rememberMe2',
option: '记住我'
}
]
]
}
]
}
]
]
}
}
},
{
type: 'submit',
label: '提交',
primary: true
}
]
],
controls: [
{
type: 'tabs',
tabs: [
{
title: '基本信息',
hash: 'tab1',
controls: [
[
{
type: 'email',
name: 'email',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
type: 'password',
name: 'password',
placeholder: '密码',
label: false
}
],
{
type: 'divider'
},
[
{
type: 'email',
name: 'email2',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
type: 'checkbox',
name: 'rememberMe',
label: false,
option: '记住我'
}
]
]
},
{
title: '其他信息',
hash: 'tab2',
controls: [
{
type: 'email',
name: 'email3',
placeholder: '请输入邮箱地址',
label: '邮箱'
},
{
type: 'divider'
},
{
type: 'checkbox',
name: 'rememberMe4',
label: '记住我'
}
]
}
]
}
]
}
]
};

View File

@ -1,126 +1,132 @@
export default {
"type": "page",
"body": {
"type": "form",
"title": "详情",
"name": "scene_detail",
"mode": "horizontal",
"submitText": "",
"submitOnChange": false,
"actions": [{
"type": "button",
"label": "修改",
"actionType": "drawer",
"drawer": {
"type": "form",
"position": "left",
"title": "修改内容",
"controls": [{
"type": "text",
"label": "标题",
"name": "name",
"required": true
}, {
"label": "描述",
"type": "text",
"name": "typeDesc",
"required": true
}, {
"label": "内容",
"type": "textarea",
"name": "contents",
"required": true
}]
type: 'page',
body: {
type: 'form',
title: '详情',
name: 'scene_detail',
mode: 'horizontal',
submitText: '',
submitOnChange: false,
actions: [
{
type: 'button',
label: '修改',
actionType: 'drawer',
drawer: {
type: 'form',
position: 'left',
title: '修改内容',
controls: [
{
type: 'text',
label: '标题',
name: 'name',
required: true
},
{
label: '描述',
type: 'text',
name: 'typeDesc',
required: true
},
{
label: '内容',
type: 'textarea',
name: 'contents',
required: true
}
}],
"controls": [
{
type: "tree",
name: "tree",
label: "树",
options: [
{
label: "Folder A",
value: 1,
children: [
{
label: "file A",
value: 2
},
{
label: "file B",
value: 3
}
]
},
{
label: "file C",
value: 4
},
{
label: "file D",
value: 5
}
]
},
{
type: "divider"
},
{
type: "tree",
name: "trees",
label: "树多选",
multiple: true,
options: [
{
label: "Folder A",
value: 1,
children: [
{
label: "file A",
value: 2
},
{
label: "file B",
value: 3
}
]
},
{
label: "file C",
value: 4
},
{
label: "file D",
value: 5
}
]
},
{
type: "divider"
},
{
name: "select",
type: "tree-select",
label: "动态选项",
source: "/api/mock2/form/getTreeOptions?waitSeconds=1",
description: '通过接口一口气拉取选项',
clearable: true,
searchable: true
},
{
type: "divider"
},
{
name: "select2",
type: "tree-select",
label: "选项自动补全",
autoComplete: "/api/mock2/tree/autoComplete?term=$term",
placeholder: "请输入",
description: '通过接口自动补全',
multiple: true
},
]
}
}
],
controls: [
{
type: 'tree',
name: 'tree',
label: '树',
options: [
{
label: 'Folder A',
value: 1,
children: [
{
label: 'file A',
value: 2
},
{
label: 'file B',
value: 3
}
]
},
{
label: 'file C',
value: 4
},
{
label: 'file D',
value: 5
}
]
}
}
},
{
type: 'divider'
},
{
type: 'tree',
name: 'trees',
label: '树多选',
multiple: true,
options: [
{
label: 'Folder A',
value: 1,
children: [
{
label: 'file A',
value: 2
},
{
label: 'file B',
value: 3
}
]
},
{
label: 'file C',
value: 4
},
{
label: 'file D',
value: 5
}
]
},
{
type: 'divider'
},
{
name: 'select',
type: 'tree-select',
label: '动态选项',
source: '/api/mock2/form/getTreeOptions?waitSeconds=1',
description: '通过接口一口气拉取选项',
clearable: true,
searchable: true
},
{
type: 'divider'
},
{
name: 'select2',
type: 'tree-select',
label: '选项自动补全',
autoComplete: '/api/mock2/tree/autoComplete?term=$term',
placeholder: '请输入',
description: '通过接口自动补全',
multiple: true
}
]
}
};

View File

@ -1,112 +1,112 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "表单验证示例",
toolbar: "<a target='_blank' href='/docs/renderers/Form/FormItem'>文档</a>",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '表单验证示例',
toolbar: "<a target='_blank' href='/docs/renderers/Form/FormItem'>文档</a>",
body: [
{
type: 'form',
autoFocus: false,
messages: {
validateFailed: '请仔细检查表单规则,部分表单项没通过验证'
},
title: '表单',
actions: [
{
type: "form",
autoFocus: false,
messages: {
'validateFailed': '请仔细检查表单规则,部分表单项没通过验证'
},
title: "表单",
actions: [
{
type: "submit",
label: "提交"
}
],
api: "/api/mock2/form/saveFormFailed?waitSeconds=2",
mode: "horizontal",
controls: [
{
type: "text",
name: "test",
label: "必填",
required: true
},
{
type: "divider"
},
{
name: "test1",
type: "email",
label: "Email"
},
{
type: "divider"
},
{
name: "url",
type: "url",
label: "Url"
},
{
type: "divider"
},
{
name: "num",
type: "text",
label: "数字",
validations: "isNumeric"
},
{
type: "divider"
},
{
name: "alpha",
type: "text",
label: "字母或数字",
validations: "isAlphanumeric"
},
{
type: "divider"
},
{
name: "int",
type: "text",
label: "整形",
validations: "isInt"
},
{
type: "divider"
},
{
name: "minLength",
type: "text",
label: "长度限制",
validations: "minLength:2,maxLength:10"
},
{
type: "divider"
},
{
name: "min",
type: "text",
label: "数值限制",
validations: "maximum:10,minimum:2"
},
{
type: "divider"
},
{
name: "reg",
type: "text",
label: "正则",
validations: "matchRegexp:/^abc/",
validationErrors: {
matchRegexp: "请输入abc开头的好么?"
}
},
{
type: "divider"
},
{
name: "test2",
type: "text",
label: "服务端验证"
}
]
type: 'submit',
label: '提交'
}
]
],
api: '/api/mock2/form/saveFormFailed?waitSeconds=2',
mode: 'horizontal',
controls: [
{
type: 'text',
name: 'test',
label: '必填',
required: true
},
{
type: 'divider'
},
{
name: 'test1',
type: 'email',
label: 'Email'
},
{
type: 'divider'
},
{
name: 'url',
type: 'url',
label: 'Url'
},
{
type: 'divider'
},
{
name: 'num',
type: 'text',
label: '数字',
validations: 'isNumeric'
},
{
type: 'divider'
},
{
name: 'alpha',
type: 'text',
label: '字母或数字',
validations: 'isAlphanumeric'
},
{
type: 'divider'
},
{
name: 'int',
type: 'text',
label: '整形',
validations: 'isInt'
},
{
type: 'divider'
},
{
name: 'minLength',
type: 'text',
label: '长度限制',
validations: 'minLength:2,maxLength:10'
},
{
type: 'divider'
},
{
name: 'min',
type: 'text',
label: '数值限制',
validations: 'maximum:10,minimum:2'
},
{
type: 'divider'
},
{
name: 'reg',
type: 'text',
label: '正则',
validations: 'matchRegexp:/^abc/',
validationErrors: {
matchRegexp: '请输入abc开头的好么?'
}
},
{
type: 'divider'
},
{
name: 'test2',
type: 'text',
label: '服务端验证'
}
]
}
]
};

File diff suppressed because it is too large Load Diff

View File

@ -1,137 +1,137 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "HBox & Grid",
"type": "page",
"body": [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'HBox & Grid',
type: 'page',
body: [
{
type: 'plain',
tpl: 'Grid 请参考 bootstrap 的 grid 布局',
inline: false,
className: 'h3 m-b-xs'
},
{
type: 'grid',
columns: [
{
"type": "plain",
"tpl": "Grid 请参考 bootstrap 的 grid 布局",
"inline": false,
"className": "h3 m-b-xs"
type: 'tpl',
tpl: 'sm-2',
sm: 2,
className: 'bg-info',
inline: false
},
{
"type": "grid",
"columns": [
{
"type": "tpl",
"tpl": "sm-2",
"sm": 2,
"className": "bg-info",
"inline": false
},
{
"type": "tpl",
"tpl": "sm-4",
"sm": 4,
"className": "bg-success",
"inline": false
},
{
"type": "tpl",
"tpl": "sm-6",
"sm": 6,
"className": "bg-primary",
"inline": false
}
]
type: 'tpl',
tpl: 'sm-4',
sm: 4,
className: 'bg-success',
inline: false
},
{
"type": "plain",
"tpl": "Hbox",
"inline": false,
"className": "h3 m-t m-b-xs"
type: 'tpl',
tpl: 'sm-6',
sm: 6,
className: 'bg-primary',
inline: false
}
]
},
{
type: 'plain',
tpl: 'Hbox',
inline: false,
className: 'h3 m-t m-b-xs'
},
{
type: 'hbox',
columns: [
{
type: 'tpl',
tpl: '平均分配',
className: 'bg-info',
inline: false
},
{
"type": "hbox",
"columns": [
{
"type": "tpl",
"tpl": "平均分配",
"className": "bg-info",
"inline": false
},
{
"type": "tpl",
"tpl": "平均分配",
"className": "bg-success",
"inline": false
},
{
"type": "tpl",
"tpl": "平均分配",
"className": "bg-primary",
"inline": false
}
]
type: 'tpl',
tpl: '平均分配',
className: 'bg-success',
inline: false
},
{
"type": "plain",
"tpl": "Hbox 部分定宽",
"inline": false,
"className": "h3 m-t m-b-xs"
type: 'tpl',
tpl: '平均分配',
className: 'bg-primary',
inline: false
}
]
},
{
type: 'plain',
tpl: 'Hbox 部分定宽',
inline: false,
className: 'h3 m-t m-b-xs'
},
{
type: 'hbox',
columns: [
{
type: 'tpl',
tpl: 'w-xs',
className: 'bg-info',
inline: false,
columnClassName: 'w-xs'
},
{
"type": "hbox",
"columns": [
{
"type": "tpl",
"tpl": "w-xs",
"className": "bg-info",
"inline": false,
"columnClassName": "w-xs"
},
{
"type": "tpl",
"tpl": "w-sm",
"className": "bg-info lter",
"inline": false,
"columnClassName": "w-sm"
},
{
"type": "tpl",
"tpl": "w",
"className": "bg-info dk",
"inline": false,
"columnClassName": "w"
},
{
"type": "tpl",
"tpl": "平均分配",
"className": "bg-success",
"inline": false
},
{
"type": "tpl",
"tpl": "平均分配",
"className": "bg-primary",
"inline": false
}
]
type: 'tpl',
tpl: 'w-sm',
className: 'bg-info lter',
inline: false,
columnClassName: 'w-sm'
},
{
"type": "plain",
"tpl": "示例",
"inline": false,
"className": "h3 m-t m-b-xs"
type: 'tpl',
tpl: 'w',
className: 'bg-info dk',
inline: false,
columnClassName: 'w'
},
{
"type": "grid",
"columns": [
{
"type": "panel",
"title": "面板1",
"className": "Panel--danger",
"body": "内容",
"sm": 4
},
{
"type": "panel",
"title": "面板2",
"className": "Panel--primary",
"body": "内容",
"sm": 8
}
]
type: 'tpl',
tpl: '平均分配',
className: 'bg-success',
inline: false
},
]
}
{
type: 'tpl',
tpl: '平均分配',
className: 'bg-primary',
inline: false
}
]
},
{
type: 'plain',
tpl: '示例',
inline: false,
className: 'h3 m-t m-b-xs'
},
{
type: 'grid',
columns: [
{
type: 'panel',
title: '面板1',
className: 'Panel--danger',
body: '内容',
sm: 4
},
{
type: 'panel',
title: '面板2',
className: 'Panel--primary',
body: '内容',
sm: 8
}
]
}
]
};

View File

@ -1,31 +1,31 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "IFrame 可以用来嵌入其他网站",
"body": [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: 'IFrame 可以用来嵌入其他网站',
body: [
{
type: 'form',
mode: 'inline',
target: 'window',
title: '',
controls: [
{
type: 'form',
mode: 'inline',
target: 'window',
title: '',
controls: [
{
type: 'text',
name: 'keywords',
addOn: {
type: 'submit',
label: '搜索',
level: 'info',
icon: 'fa fa-search pull-left'
}
}
]
},
{
type: 'iframe',
className: 'b-a',
src: "https://www.baidu.com/s?wd=${keywords|url_encode}",
height: 500
type: 'text',
name: 'keywords',
addOn: {
type: 'submit',
label: '搜索',
level: 'info',
icon: 'fa fa-search pull-left'
}
}
]
}
]
},
{
type: 'iframe',
className: 'b-a',
src: 'https://www.baidu.com/s?wd=${keywords|url_encode}',
height: 500
}
]
};

View File

@ -1,174 +1,173 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
title: "表单与列表之间的联动",
body: [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '表单与列表之间的联动',
body: [
{
title: '',
type: 'form',
mode: 'inline',
target: 'list',
wrapWithPanel: false,
className: 'm-b',
controls: [
{
title: "",
type: 'form',
mode: 'inline',
target: 'list',
wrapWithPanel: false,
className: 'm-b',
controls: [
{
type: "text",
name: "keywords",
placeholder: "通过关键字搜索",
clearable: true,
addOn: {
type: 'submit',
icon: 'fa fa-search',
level: 'primary'
}
},
]
},
{
type: "crud",
name: 'list',
api: "/api/sample",
mode: "list",
listItem: {
actions: [
{
type: "button",
icon: "fa fa-eye",
actionType: "dialog",
dialog: {
title: "查看",
body: {
type: "form",
controls: [
{
type: "static",
name: "engine",
label: "Engine"
},
{
type: "divider"
},
{
type: "static",
name: "browser",
label: "Browser"
},
{
type: "divider"
},
{
type: "static",
name: "platform",
label: "Platform(s)"
},
{
type: "divider"
},
{
type: "static",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "static",
name: "grade",
label: "CSS grade"
}
]
}
}
},
{
type: "button",
icon: "fa fa-pencil",
actionType: "dialog",
dialog: {
title: "编辑",
body: {
type: "form",
name: "sample-edit-form",
api: "/api/sample/$id",
controls: [
{
type: "text",
name: "engine",
label: "Engine",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "browser",
label: "Browser",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "platform",
label: "Platform(s)",
required: true
},
{
type: "divider"
},
{
type: "text",
name: "version",
label: "Engine version"
},
{
type: "divider"
},
{
type: "text",
name: "grade",
label: "CSS grade"
}
]
}
}
},
{
type: "button",
icon: "fa fa-times text-danger",
actionType: "ajax",
confirmText: "您确认要删除?",
api: "delete:/api/sample/$id"
}
],
body: [
{
name: "engine",
label: "Rendering engine",
labelClassName: "w-sm"
},
[
{
name: "browser",
label: "Browser",
labelClassName: "w-sm"
},
{
name: "platform",
label: "Platform(s)",
labelClassName: "w-sm"
}
],
{
name: "version",
label: "Engine version",
labelClassName: "w-sm"
}
type: 'text',
name: 'keywords',
placeholder: '通过关键字搜索',
clearable: true,
addOn: {
type: 'submit',
icon: 'fa fa-search',
level: 'primary'
}
}
]
},
{
type: 'crud',
name: 'list',
api: '/api/sample',
mode: 'list',
listItem: {
actions: [
{
type: 'button',
icon: 'fa fa-eye',
actionType: 'dialog',
dialog: {
title: '查看',
body: {
type: 'form',
controls: [
{
type: 'static',
name: 'engine',
label: 'Engine'
},
{
type: 'divider'
},
{
type: 'static',
name: 'browser',
label: 'Browser'
},
{
type: 'divider'
},
{
type: 'static',
name: 'platform',
label: 'Platform(s)'
},
{
type: 'divider'
},
{
type: 'static',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'static',
name: 'grade',
label: 'CSS grade'
}
]
}
}
}]
};
},
{
type: 'button',
icon: 'fa fa-pencil',
actionType: 'dialog',
dialog: {
title: '编辑',
body: {
type: 'form',
name: 'sample-edit-form',
api: '/api/sample/$id',
controls: [
{
type: 'text',
name: 'engine',
label: 'Engine',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'browser',
label: 'Browser',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'platform',
label: 'Platform(s)',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'version',
label: 'Engine version'
},
{
type: 'divider'
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
}
},
{
type: 'button',
icon: 'fa fa-times text-danger',
actionType: 'ajax',
confirmText: '您确认要删除?',
api: 'delete:/api/sample/$id'
}
],
body: [
{
name: 'engine',
label: 'Rendering engine',
labelClassName: 'w-sm'
},
[
{
name: 'browser',
label: 'Browser',
labelClassName: 'w-sm'
},
{
name: 'platform',
label: 'Platform(s)',
labelClassName: 'w-sm'
}
],
{
name: 'version',
label: 'Engine version',
labelClassName: 'w-sm'
}
]
}
}
]
};

View File

@ -1,67 +1,67 @@
export default {
type: 'page',
title: '表单与表单之间的联动',
aside: {
type: 'form',
target: 'detailForm',
className: 'wrapper-sm', //
wrapWithPanel: false, // panel
controls: [
{
type: 'text',
placeholder: '关键字',
name: 'keywords',
addOn: {
type: 'submit',
label: '搜索',
primary: true
}
},
type: 'page',
title: '表单与表单之间的联动',
aside: {
type: 'form',
target: 'detailForm',
className: 'wrapper-sm', //
wrapWithPanel: false, // panel
controls: [
{
type: 'text',
placeholder: '关键字',
name: 'keywords',
addOn: {
type: 'submit',
label: '搜索',
primary: true
}
},
'<span class="text-danger">请在此输入内容后点击搜索</sapn>'
]
},
body: {
name: 'detailForm',
type: 'form',
mode: 'horizontal',
title: '',
initApi: '/api/mock2/form/initData?keywords=${keywords}',
actions: [],
controls: [
'Form 模型除了用来提交数据外,还比较适合用来做详情数据的展示',
{
type: 'divider'
},
'<span class="text-danger">请在此输入内容后点击搜索</sapn>'
]
},
body: {
name: 'detailForm',
type: 'form',
mode: 'horizontal',
title: '',
initApi: '/api/mock2/form/initData?keywords=${keywords}',
actions: [],
controls: [
'Form 模型除了用来提交数据外,还比较适合用来做详情数据的展示',
{
type: 'divider'
},
{
label: '名称',
type: 'static',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '名称',
type: 'static',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '作者',
type: 'static',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '作者',
type: 'static',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '输入信息',
type: 'static',
labelClassName: 'text-muted',
name: 'info'
},
{
label: '输入信息',
type: 'static',
labelClassName: 'text-muted',
name: 'info'
},
{
label: '请求时间',
type: 'static-datetime',
labelClassName: 'text-muted',
format: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
}
}
{
label: '请求时间',
type: 'static-datetime',
labelClassName: 'text-muted',
format: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
}
};

View File

@ -1,306 +1,305 @@
export default {
type: 'page',
title: '表单初始数据自动重新拉取',
body: [
type: 'page',
title: '表单初始数据自动重新拉取',
body: [
{
type: 'form',
mode: 'horizontal',
title: '监听表单内部的修改',
initApi: '/api/mock2/form/initData?tpl=${tpl}',
actions: [],
controls: [
'<span class="text-danger">当 <code>initApi</code> 中有变量,且变量的值发生了变化了,则该表单就会重新初始数据。</span>',
{
type: 'form',
mode: 'horizontal',
title: '监听表单内部的修改',
initApi: '/api/mock2/form/initData?tpl=${tpl}',
actions: [],
controls: [
'<span class="text-danger">当 <code>initApi</code> 中有变量,且变量的值发生了变化了,则该表单就会重新初始数据。</span>',
{
type: 'divider'
},
{
label: '数据模板',
type: 'select',
labelClassName: 'text-muted',
name: 'tpl',
value: 'tpl1',
inline: true,
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
],
description: '<span class="text-danger">请修改这里看效果</span>'
},
{
label: '名称',
type: 'static',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '作者',
type: 'static',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '请求时间',
type: 'static-datetime',
labelClassName: 'text-muted',
format: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
},
{
type: 'grid',
columns: [
{
type: 'form',
mode: 'horizontal',
title: '自动填充',
actions: [],
controls: [
{
label: '数据模板',
type: 'select',
labelClassName: 'text-muted',
name: 'tpl',
value: 'tpl1',
inline: true,
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
],
description: '<span class="text-danger">请修改这里看效果</span>'
},
'<div class="text-danger m-b">如果 <code>initApi</code> 已经暂用,用 <code>service</code>一样可以拉取值填充,同样以下 api 值发生变化时会自动填充。</div>',
{
type: 'service',
api: '/api/mock2/form/initData?tpl=${tpl}',
body: {
controls: [
{
label: '名称',
type: 'text',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '作者',
type: 'text',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '请求时间',
type: 'datetime',
labelClassName: 'text-muted',
inputFormat: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
}
}
]
},
{
type: 'form',
mode: 'horizontal',
title: '手动填充',
actions: [],
controls: [
{
type: 'group',
label: '数据模板',
labelClassName: 'text-muted',
controls: [
{
type: 'select',
name: 'tpl',
value: 'tpl1',
mode: 'inline',
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
]
},
{
mode: 'inline',
type: 'button',
label: '获取',
level: 'dark',
actionType: 'reload',
target: 'theService'
}
]
},
'<div class="text-danger m-b">如果不想自动填充,自动填充,则把参数放在 data 里面,就不会监控变化自动拉取了,同时把 <code>servcie</code> 的初始拉取关掉,然后来个刷新目标组件的按钮。</div>',
{
type: 'service',
name: 'theService',
api: {
method: 'get',
url: '/api/mock2/form/initData',
data: {
tpl: '${tpl}'
}
},
body: {
controls: [
{
label: '名称',
type: 'text',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '作者',
type: 'text',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '请求时间',
type: 'datetime',
labelClassName: 'text-muted',
inputFormat: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
}
}
]
}
]
type: 'divider'
},
{
type: 'divider'
label: '数据模板',
type: 'select',
labelClassName: 'text-muted',
name: 'tpl',
value: 'tpl1',
inline: true,
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
],
description: '<span class="text-danger">请修改这里看效果</span>'
},
{
type: 'form',
title: '条件表单',
target: 'detailForm',
submitOnInit: true,
mode: 'inline',
controls: [
{
label: '数据模板',
type: 'select',
labelClassName: 'text-muted',
name: 'tpl',
value: 'tpl1',
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
]
},
{
type: 'submit',
label: '提交',
primary: true
}
]
label: '名称',
type: 'static',
labelClassName: 'text-muted',
name: 'name'
},
{
name: 'detailForm',
type: 'form',
mode: 'horizontal',
title: '响应表单',
initApi: '/api/mock2/form/initData?tpl=${tpl}',
initFetchOn: 'data.tpl',
actions: [],
controls: [
'<span class="text-danger">当 <code>initApi</code> 中有变量,且变量的值发生了变化了,则该表单就会重新初始数据。</span>',
{
type: 'divider'
},
{
label: '名称',
type: 'static',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '作者',
type: 'static',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '请求时间',
type: 'static-datetime',
labelClassName: 'text-muted',
format: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
label: '作者',
type: 'static',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '请求时间',
type: 'static-datetime',
labelClassName: 'text-muted',
format: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
}
]
},
{
type: 'grid',
columns: [
{
type: 'form',
mode: 'horizontal',
title: '自动填充',
actions: [],
controls: [
{
label: '数据模板',
type: 'select',
labelClassName: 'text-muted',
name: 'tpl',
value: 'tpl1',
inline: true,
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
],
description: '<span class="text-danger">请修改这里看效果</span>'
},
'<div class="text-danger m-b">如果 <code>initApi</code> 已经暂用,用 <code>service</code>一样可以拉取值填充,同样以下 api 值发生变化时会自动填充。</div>',
{
type: 'service',
api: '/api/mock2/form/initData?tpl=${tpl}',
body: {
controls: [
{
label: '名称',
type: 'text',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '作者',
type: 'text',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '请求时间',
type: 'datetime',
labelClassName: 'text-muted',
inputFormat: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
}
}
]
},
{
type: 'form',
mode: 'horizontal',
title: '手动填充',
actions: [],
controls: [
{
type: 'group',
label: '数据模板',
labelClassName: 'text-muted',
controls: [
{
type: 'select',
name: 'tpl',
value: 'tpl1',
mode: 'inline',
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
]
},
{
mode: 'inline',
type: 'button',
label: '获取',
level: 'dark',
actionType: 'reload',
target: 'theService'
}
]
},
'<div class="text-danger m-b">如果不想自动填充,自动填充,则把参数放在 data 里面,就不会监控变化自动拉取了,同时把 <code>servcie</code> 的初始拉取关掉,然后来个刷新目标组件的按钮。</div>',
{
type: 'service',
name: 'theService',
api: {
method: 'get',
url: '/api/mock2/form/initData',
data: {
tpl: '${tpl}'
}
},
body: {
controls: [
{
label: '名称',
type: 'text',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '作者',
type: 'text',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '请求时间',
type: 'datetime',
labelClassName: 'text-muted',
inputFormat: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
}
}
]
}
]
},
{
type: 'divider'
},
{
type: 'form',
title: '条件表单',
target: 'detailForm',
submitOnInit: true,
mode: 'inline',
controls: [
{
label: '数据模板',
type: 'select',
labelClassName: 'text-muted',
name: 'tpl',
value: 'tpl1',
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
]
},
{
type: 'submit',
label: '提交',
primary: true
}
]
},
{
name: 'detailForm',
type: 'form',
mode: 'horizontal',
title: '响应表单',
initApi: '/api/mock2/form/initData?tpl=${tpl}',
initFetchOn: 'data.tpl',
actions: [],
controls: [
'<span class="text-danger">当 <code>initApi</code> 中有变量,且变量的值发生了变化了,则该表单就会重新初始数据。</span>',
{
type: 'divider'
},
{
label: '名称',
type: 'static',
labelClassName: 'text-muted',
name: 'name'
},
{
label: '作者',
type: 'static',
labelClassName: 'text-muted',
name: 'author'
},
{
label: '请求时间',
type: 'static-datetime',
labelClassName: 'text-muted',
format: 'YYYY-MM-DD HH:mm:ss',
name: 'date'
}
]
}
]
};

View File

@ -1,60 +1,60 @@
export default {
type: 'page',
title: '表单选线之间的远程联动',
body: {
type: 'form',
mode: 'horizontal',
title: '',
actions: [],
controls: [
'<p class="text-danger">表单选项可以设置 source 通过 API 远程拉取,同时如果 source 中有变量的话,变量值发生变化就会重新拉取,达到联动效果。</p>',
{
type: 'divider'
},
type: 'page',
title: '表单选线之间的远程联动',
body: {
type: 'form',
mode: 'horizontal',
title: '',
actions: [],
controls: [
'<p class="text-danger">表单选项可以设置 source 通过 API 远程拉取,同时如果 source 中有变量的话,变量值发生变化就会重新拉取,达到联动效果。</p>',
{
type: 'divider'
},
{
label: '选项1',
type: 'select',
labelClassName: 'text-muted',
name: 'a',
inline: true,
options: [
{
label: '选项1',
value: 1
},
{
label: '选项1',
type: 'select',
labelClassName: 'text-muted',
name: 'a',
inline: true,
options: [
{
label: '选项1',
value: 1
},
{
label: '选项2',
value: 2
},
{
label: '选项2',
value: 2
},
{
label: '选项3',
value: 3
}
]
},
{
label: '选项2',
type: 'select',
labelClassName: 'text-muted',
name: 'b',
inline: true,
source: '/api/mock2/options/level2?a=${a}',
initFetchOn: 'data.a'
},
{
label: '选项3',
type: 'select',
labelClassName: 'text-muted',
name: 'c',
inline: true,
visibleOn: 'data.b',
source: '/api/mock2/options/level3?b=${b}'
},
{
label: '选项3',
value: 3
}
]
}
}
},
{
label: '选项2',
type: 'select',
labelClassName: 'text-muted',
name: 'b',
inline: true,
source: '/api/mock2/options/level2?a=${a}',
initFetchOn: 'data.a'
},
{
label: '选项3',
type: 'select',
labelClassName: 'text-muted',
name: 'c',
inline: true,
visibleOn: 'data.b',
source: '/api/mock2/options/level3?b=${b}'
}
]
}
};

View File

@ -1,68 +1,68 @@
export default {
type: 'page',
title: '表单选线的联动',
body: {
type: 'form',
mode: 'horizontal',
title: '',
actions: [],
controls: [
'<p class="text-danger">表单选项内也能联动,通过配置 visibleOn、hiddenOn或者disabledOn</p>',
{
type: 'divider'
},
type: 'page',
title: '表单选线的联动',
body: {
type: 'form',
mode: 'horizontal',
title: '',
actions: [],
controls: [
'<p class="text-danger">表单选项内也能联动,通过配置 visibleOn、hiddenOn或者disabledOn</p>',
{
type: 'divider'
},
{
label: '选项1',
type: 'list',
multiple: false,
labelClassName: 'text-muted',
name: 'a',
inline: true,
options: [
{
label: '选项1',
value: 1
},
{
label: '选项1',
type: 'list',
multiple: false,
labelClassName: 'text-muted',
name: 'a',
inline: true,
options: [
{
label: '选项1',
value: 1
},
{
label: '选项2',
value: 2
},
{
label: '选项2',
value: 2
},
{
label: '选项3',
value: 3
}
]
},
{
label: '选项2',
type: 'radios',
labelClassName: 'text-muted',
name: 'b',
inline: true,
options: [
{
label: '选项1',
value: 1,
disabledOn: 'data.a == 1'
},
{
label: '选项2',
value: 2,
hiddenOn: 'data.a == 2'
},
{
label: '选项3',
value: 3,
visibleOn: 'data.a == 3'
}
]
}
{
label: '选项3',
value: 3
}
]
}
}
},
{
label: '选项2',
type: 'radios',
labelClassName: 'text-muted',
name: 'b',
inline: true,
options: [
{
label: '选项1',
value: 1,
disabledOn: 'data.a == 1'
},
{
label: '选项2',
value: 2,
hiddenOn: 'data.a == 2'
},
{
label: '选项3',
value: 3,
visibleOn: 'data.a == 3'
}
]
}
]
}
};

View File

@ -1,49 +1,49 @@
export default {
$schema: "https://houtai.baidu.com/v2/schemas/page.json#",
type: 'page',
title: "地址栏变化自动更新",
initApi: '/api/mock2/form/initData?id=${id}',
aside: {
type: 'wrapper',
size: 'xs',
className: '',
body: {
type: 'nav',
stacked: true,
links: [
{
label: '页面1',
to: '?id=1'
},
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
type: 'page',
title: '地址栏变化自动更新',
initApi: '/api/mock2/form/initData?id=${id}',
aside: {
type: 'wrapper',
size: 'xs',
className: '',
body: {
type: 'nav',
stacked: true,
links: [
{
label: '页面1',
to: '?id=1'
},
{
label: '页面2',
children: [
{
label: '页面2-1',
to: '?id=2-1',
},
{
label: '页面2-2',
to: '?id=2-2',
},
{
label: '页面2-3disabled',
disabled: true,
to: '?id=2-3',
},
]
},
{
label: '页面2',
children: [
{
label: '页面2-1',
to: '?id=2-1'
},
{
label: '页面2-2',
to: '?id=2-2'
},
{
label: '页面2-3disabled',
disabled: true,
to: '?id=2-3'
}
]
},
{
label: '页面3',
to: '?id=3'
}
]
{
label: '页面3',
to: '?id=3'
}
},
body: [
'<p><span class="text-danger">注意 page 渲染器的 `initApi` 中有变量跟地址栏中变量关联,只要值发生了变化,就会重新拉取一次 initApi。</sapn></p>',
"<p>这些数据是通过 initApi 拉取到的数据。 `\\$infoId`: <span class=\"text-danger\">${infoId|default:空}</span></p>"
]
]
}
},
body: [
'<p><span class="text-danger">注意 page 渲染器的 `initApi` 中有变量跟地址栏中变量关联,只要值发生了变化,就会重新拉取一次 initApi。</sapn></p>',
'<p>这些数据是通过 initApi 拉取到的数据。 `\\$infoId`: <span class="text-danger">${infoId|default:空}</span></p>'
]
};

View File

@ -11,180 +11,220 @@ import NestedLinks from '../../src/components/AsideNav';
import {Portal} from 'react-overlays';
class CodePreview extends React.Component {
state = {
PlayGround: null
};
componentDidMount() {
require(['./Play'], (component) => this.setState({
PlayGround: component.default
}))
}
state = {
PlayGround: null
};
componentDidMount() {
require(['./Play'], component =>
this.setState({
PlayGround: component.default
}));
}
render() {
const {
container,
height,
setAsideFolded,
setHeaderVisible,
...rest
} = this.props;
render() {
const {
container,
height,
setAsideFolded,
setHeaderVisible,
...rest
} = this.props;
const PlayGround = this.state.PlayGround;
// .markdown-body Overlay
const PlayGround = this.state.PlayGround;
// .markdown-body Overlay
return (
<div>
<span style={{display: 'block', height: height}} ref="span"></span>
{PlayGround ? <Overlay
container={container}
target={() => this.refs.span}
placement="bottom"
show
>
<PopOver offset={{x: 0, y: -height}} style={{height}} className="doc-shcema-preview-popover">
<div className="doc-schema-preview">
<PlayGround {...rest} vertical />
</div>
</PopOver>
</Overlay> : null }
</div>
);
}
return (
<div>
<span style={{display: 'block', height: height}} ref="span" />
{PlayGround ? (
<Overlay
container={container}
target={() => this.refs.span}
placement="bottom"
show
>
<PopOver
offset={{x: 0, y: -height}}
style={{height}}
className="doc-shcema-preview-popover"
>
<div className="doc-schema-preview">
<PlayGround {...rest} vertical />
</div>
</PopOver>
</Overlay>
) : null}
</div>
);
}
}
function isActive(link, location) {
return !!(link.fullPath && link.fullPath === location.hash);
return !!(link.fullPath && link.fullPath === location.hash);
}
export default function(doc) {
return class extends React.Component {
static displayName = 'MarkdownRenderer';
ref = null;
doms = [];
constructor(props) {
super(props);
this.divRef = this.divRef.bind(this);
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
this.renderSchema();
if (location.hash && location.hash.length > 1) {
//
if (window.history && 'scrollRestoration' in window.history) {
window.history.scrollRestoration = 'manual';
}
const dom = document.querySelector(`[name="${location.hash.substring(1)}"]`);
dom && dom.scrollIntoView();
}
}
componentDidUpdate() {
this.renderSchema();
}
componentWillUnmount() {
this.doms.forEach(dom => ReactDOM.unmountComponentAtNode(dom));
}
handleClick(e) {
const href = e.target.getAttribute('href');
if (href && href[0] !== '#' && !/^http/.test(href)) {
e.preventDefault();
this.props.push(href);
}
}
divRef(ref) {
this.ref = ref;
if (ref) {
ref.innerHTML = doc.html;
}
}
renderSchema() {
const scripts = document.querySelectorAll('script[type="text/schema"]');
if (!scripts && !scripts.length) {
return;
}
for (let i = 0, len = scripts.length; i < len; i++) {
let script = scripts[i];
let props = {};
[].slice.apply(script.attributes).forEach(item => {
props[item.name] = item.value
});
let dom = document.createElement('div');
let height = props.height ? parseInt(props.height, 10) : 200;
dom.setAttribute("class", "doc-play-ground")
dom.setAttribute("style", `height: ${height}px;`);
script.parentNode.replaceChild(dom, script);
this.doms.push(dom);
ReactDOM.unstable_renderSubtreeIntoContainer(this, (
<LazyComponent
{...this.props}
container={() => ReactDOM.findDOMNode(this)}
height={height}
component={CodePreview}
code={script.innerText}
scope={props.scope}
unMountOnHidden
placeholder="加载中,请稍后。。。"
/>
), dom);
}
}
render() {
const {location} = this.props;
return (
<div className="pos-rlt text-left">
{doc.title ? (<TitleBar title={doc.title} />) : null}
<div className="markdown-body" ref={this.divRef}>Doc</div>
{doc.toc && doc.toc.children && doc.toc.children.length > 1 ? (
<Portal
container={() => document.querySelector('#asideInner')}
>
<NestedLinks
navigations={[doc.toc]}
renderLink={({link, active, toggleExpand, depth, classnames: cx}) => {
let children = [];
if (link.children) {
children.push(
<span
key="expand-toggle"
className={cx(`AsideNav-itemArrow`)}
></span>
);
}
link.badge && children.push(
<b key="badge" className={cx('AsideNav-itemBadge', link.badgeClassName || 'bg-info')}>{link.badge}</b>
);
depth === 1 && children.push(
<i key="icon" className={cx("AsideNav-itemIcon fa fa-flag")} />
);
children.push(
<span key="label" className={cx("AsideNav-itemLabel")}>{link.label}</span>
);
return link.fragment ? (<a href={`#${link.fragment}`}>{children}</a>) : (<a onClick={link.children ? () => toggleExpand(link) : null}>{children}</a>);
}}
isActive={link => isActive(link, location)}
/>
</Portal>
) : null}
</div>
);
}
return class extends React.Component {
static displayName = 'MarkdownRenderer';
ref = null;
doms = [];
constructor(props) {
super(props);
this.divRef = this.divRef.bind(this);
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
this.renderSchema();
if (location.hash && location.hash.length > 1) {
//
if (window.history && 'scrollRestoration' in window.history) {
window.history.scrollRestoration = 'manual';
}
const dom = document.querySelector(
`[name="${location.hash.substring(1)}"]`
);
dom && dom.scrollIntoView();
}
}
componentDidUpdate() {
this.renderSchema();
}
componentWillUnmount() {
this.doms.forEach(dom => ReactDOM.unmountComponentAtNode(dom));
}
handleClick(e) {
const href = e.target.getAttribute('href');
if (href && href[0] !== '#' && !/^http/.test(href)) {
e.preventDefault();
this.props.push(href);
}
}
divRef(ref) {
this.ref = ref;
if (ref) {
ref.innerHTML = doc.html;
}
}
renderSchema() {
const scripts = document.querySelectorAll('script[type="text/schema"]');
if (!scripts && !scripts.length) {
return;
}
for (let i = 0, len = scripts.length; i < len; i++) {
let script = scripts[i];
let props = {};
[].slice.apply(script.attributes).forEach(item => {
props[item.name] = item.value;
});
let dom = document.createElement('div');
let height = props.height ? parseInt(props.height, 10) : 200;
dom.setAttribute('class', 'doc-play-ground');
dom.setAttribute('style', `height: ${height}px;`);
script.parentNode.replaceChild(dom, script);
this.doms.push(dom);
ReactDOM.unstable_renderSubtreeIntoContainer(
this,
<LazyComponent
{...this.props}
container={() => ReactDOM.findDOMNode(this)}
height={height}
component={CodePreview}
code={script.innerText}
scope={props.scope}
unMountOnHidden
placeholder="加载中,请稍后。。。"
/>,
dom
);
}
}
render() {
const {location} = this.props;
return (
<div className="pos-rlt text-left">
{doc.title ? <TitleBar title={doc.title} /> : null}
<div className="markdown-body" ref={this.divRef}>
Doc
</div>
{doc.toc && doc.toc.children && doc.toc.children.length > 1 ? (
<Portal container={() => document.querySelector('#asideInner')}>
<NestedLinks
navigations={[doc.toc]}
renderLink={({
link,
active,
toggleExpand,
depth,
classnames: cx
}) => {
let children = [];
if (link.children) {
children.push(
<span
key="expand-toggle"
className={cx(`AsideNav-itemArrow`)}
/>
);
}
link.badge &&
children.push(
<b
key="badge"
className={cx(
'AsideNav-itemBadge',
link.badgeClassName || 'bg-info'
)}
>
{link.badge}
</b>
);
depth === 1 &&
children.push(
<i
key="icon"
className={cx('AsideNav-itemIcon fa fa-flag')}
/>
);
children.push(
<span key="label" className={cx('AsideNav-itemLabel')}>
{link.label}
</span>
);
return link.fragment ? (
<a href={`#${link.fragment}`}>{children}</a>
) : (
<a
onClick={link.children ? () => toggleExpand(link) : null}
>
{children}
</a>
);
}}
isActive={link => isActive(link, location)}
/>
</Portal>
) : null}
</div>
);
}
};
}

View File

@ -1,27 +1,27 @@
export default {
type: 'page',
title: '标题',
remark: '提示 Tip',
body: [
`
type: 'page',
title: '标题',
remark: '提示 Tip',
body: [
`
<p>\`initApi\` 拉取失败时,页面内容区会显示对应的错误信息。</p>
<p>其他提示示例</p>
`,
{
type: 'alert',
level: 'success',
body: `温馨提示:对页面功能的提示说明,绿色为正向类的消息提示`
},
{
type: 'alert',
level: 'success',
body: `温馨提示:对页面功能的提示说明,绿色为正向类的消息提示`
},
{
type: 'alert',
level: 'warning',
body: `您的私有网络已达到配额,如需更多私有网络,可以通过<a>工单</a>申请`
}
],
aside: '边栏',
toolbar: '工具栏',
initApi: '/api/mock2/page/initDataError'
}
{
type: 'alert',
level: 'warning',
body: `您的私有网络已达到配额,如需更多私有网络,可以通过<a>工单</a>申请`
}
],
aside: '边栏',
toolbar: '工具栏',
initApi: '/api/mock2/page/initDataError'
};

View File

@ -1,23 +1,23 @@
export default {
type: 'page',
title: '表单页面',
body: {
type: 'form',
mode: 'horizontal',
title: '',
api: '/api/mock2/form/saveForm',
controls: [
{
label: 'Name',
type: 'text',
name: 'name'
},
type: 'page',
title: '表单页面',
body: {
type: 'form',
mode: 'horizontal',
title: '',
api: '/api/mock2/form/saveForm',
controls: [
{
label: 'Name',
type: 'text',
name: 'name'
},
{
label: 'Email',
type: 'email',
name: 'email'
}
]
}
}
{
label: 'Email',
type: 'email',
name: 'email'
}
]
}
};

View File

@ -1,9 +1,9 @@
export default {
type: 'page',
title: '标题',
remark: '提示 Tip',
body: "内容部分. 可以使用 \\${var} 获取变量。如: `\\$date`: ${date}",
aside: '边栏部分',
toolbar: '工具栏',
initApi: '/api/mock2/page/initData'
}
type: 'page',
title: '标题',
remark: '提示 Tip',
body: '内容部分. 可以使用 \\${var} 获取变量。如: `\\$date`: ${date}',
aside: '边栏部分',
toolbar: '工具栏',
initApi: '/api/mock2/page/initData'
};

View File

@ -1,7 +1,5 @@
import React from 'react';
import {
toast
} from '../../src/components/Toast';
import {toast} from '../../src/components/Toast';
import {render} from '../../src/index';
import axios from 'axios';
import Frame from 'react-frame-component';
@ -18,14 +16,14 @@ const DEFAULT_CONTENT = `{
}`;
const scopes = {
'none': ``,
none: ``,
'body': `{
body: `{
"type": "page",
"body": SCHEMA_PLACEHOLDER
}`,
'form': `{
form: `{
"type": "page",
"body": {
"title": "",
@ -39,7 +37,7 @@ const scopes = {
}
}`,
'form-item': `{
'form-item': `{
"type": "page",
"body": {
"title": "",
@ -53,229 +51,247 @@ const scopes = {
"actions": []
}
}`
};
export default class PlayGround extends React.Component {
state = null;
startX = 0;
oldContents = '';
frameTemplate;
state = null;
startX = 0;
oldContents = '';
frameTemplate;
static defaultProps = {
useIFrame: false,
vertical: false
};
static defaultProps = {
useIFrame: false,
vertical: false
constructor(props) {
super(props);
const schema = this.buildSchema(props.code || DEFAULT_CONTENT, props);
this.state = {
asideWidth: props.asideWidth || Math.max(300, window.innerWidth * 0.3),
schema: schema,
schemaCode: JSON.stringify(schema, null, 2)
};
constructor(props) {
super(props);
const schema = this.buildSchema(props.code || DEFAULT_CONTENT, props);
this.state = {
asideWidth: props.asideWidth || Math.max(300, window.innerWidth * 0.3),
schema: schema,
schemaCode: JSON.stringify(schema, null, 2)
this.handleMouseDown = this.handleMouseDown.bind(this);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseUp = this.handleMouseUp.bind(this);
this.removeWindowEvents = this.removeWindowEvents.bind(this);
this.handleChange = this.handleChange.bind(this);
this.schemaProps = {
style: {
height: '100%'
}
};
this.env = {
updateLocation: () => {},
fetcher: config => {
config = {
dataType: 'json',
...config
};
this.handleMouseDown = this.handleMouseDown.bind(this);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseUp = this.handleMouseUp.bind(this);
this.removeWindowEvents = this.removeWindowEvents.bind(this);
this.handleChange = this.handleChange.bind(this);
this.schemaProps = {
style: {
height: '100%'
}
};
this.env = {
updateLocation: () => {
},
fetcher: config => {
config = {
dataType: 'json',
...config
};
if (config.dataType === 'json' && config.data) {
config.data = JSON.stringify(config.data)
config.headers = config.headers || {};
config.headers['Content-Type'] = 'application/json';
}
return axios[config.method](config.url, config.data, config);
},
notify: (type, msg) => toast[type] ? toast[type](msg, type === 'error' ? '系统错误' : '系统消息') : console.warn('[Notify]', type, msg)
if (config.dataType === 'json' && config.data) {
config.data = JSON.stringify(config.data);
config.headers = config.headers || {};
config.headers['Content-Type'] = 'application/json';
}
const links = [].slice.call(document.head.querySelectorAll('link,style')).map(item => item.outerHTML);
this.frameTemplate = `<!DOCTYPE html><html><head>${links.join('')}</head><body><div></div></body></html>`;
return axios[config.method](config.url, config.data, config);
},
notify: (type, msg) =>
toast[type]
? toast[type](msg, type === 'error' ? '系统错误' : '系统消息')
: console.warn('[Notify]', type, msg)
};
const links = [].slice
.call(document.head.querySelectorAll('link,style'))
.map(item => item.outerHTML);
this.frameTemplate = `<!DOCTYPE html><html><head>${links.join(
''
)}</head><body><div></div></body></html>`;
}
componentWillReceiveProps(nextprops) {
const props = this.props;
if (props.code !== nextprops.code) {
const schema = this.buildSchema(
nextprops.code || DEFAULT_CONTENT,
nextprops
);
this.setState({
schema: schema,
schemaCode: JSON.stringify(schema, null, 2)
});
}
}
componentWillReceiveProps(nextprops) {
const props = this.props;
componentDidMount() {
this.props.setAsideFolded && this.props.setAsideFolded(true);
}
if (props.code !== nextprops.code) {
const schema = this.buildSchema(nextprops.code || DEFAULT_CONTENT, nextprops);
this.setState({
schema: schema,
schemaCode: JSON.stringify(schema, null, 2)
});
}
}
componentWillUnmount() {
this.props.setAsideFolded && this.props.setAsideFolded(false);
}
componentDidMount() {
this.props.setAsideFolded && this.props.setAsideFolded(true);
}
buildSchema(schemaContent, props = this.props) {
const query = props.location.query;
componentWillUnmount() {
this.props.setAsideFolded && this.props.setAsideFolded(false);
}
try {
const scope = query.scope || props.scope;
buildSchema(schemaContent, props = this.props) {
const query = props.location.query;
try {
const scope = query.scope || props.scope;
if (scope && scopes[scope]) {
schemaContent = scopes[scope].replace('SCHEMA_PLACEHOLDER', schemaContent);
}
schemaContent = stripJsonComments(schemaContent).replace(/('|")raw:/g, '$1'); //
return JSON.parse(schemaContent);
} catch (e) {
console.error(this.formatMessage(e.message, schemaContent));
}
return {};
}
formatMessage(message, input) {
if (/position\s?(\d+)$/.test(message)) {
const lines = input.substring(0, parseInt(RegExp.$1, 10)).split(/\n|\r\n|\r/);
message = `Json 语法错误,请检测。出错位置:${lines.length},列:${lines[lines.length -1].length}`;
}
return message;
}
renderPreview() {
const schema = this.state.schema;
if (!this.props.useIFrame) {
return render(schema, this.schemaProps, this.env);
}
return (
<Frame
width="100%"
height="100%"
frameBorder={0}
initialContent={this.frameTemplate}
>
{render(schema, this.schemaProps, this.env)}
</Frame>
if (scope && scopes[scope]) {
schemaContent = scopes[scope].replace(
'SCHEMA_PLACEHOLDER',
schemaContent
);
}
schemaContent = stripJsonComments(schemaContent).replace(
/('|")raw:/g,
'$1'
); //
return JSON.parse(schemaContent);
} catch (e) {
console.error(this.formatMessage(e.message, schemaContent));
}
handleChange(value) {
this.setState({
schemaCode: value
});
return {};
}
try {
const schema = JSON.parse(value);
this.setState({
schema
});
} catch (e) {
//ignore
}
formatMessage(message, input) {
if (/position\s?(\d+)$/.test(message)) {
const lines = input
.substring(0, parseInt(RegExp.$1, 10))
.split(/\n|\r\n|\r/);
message = `Json 语法错误,请检测。出错位置:${lines.length},列:${
lines[lines.length - 1].length
}`;
}
handleMouseDown(e) {
this.startX = e.clientX;
this.startWidth = this.state.asideWidth;
return message;
}
// this.startPosition.y = e.clientY;
renderPreview() {
const schema = this.state.schema;
window.addEventListener('mouseup', this.handleMouseUp);
window.addEventListener('mousemove', this.handleMouseMove);
return false;
if (!this.props.useIFrame) {
return render(schema, this.schemaProps, this.env);
}
handleMouseMove(e) {
const diff = this.startX - e.clientX;
e.preventDefault();
return (
<Frame
width="100%"
height="100%"
frameBorder={0}
initialContent={this.frameTemplate}
>
{render(schema, this.schemaProps, this.env)}
</Frame>
);
}
this.setState({
asideWidth: Math.min(800, Math.max(200, this.startWidth + diff))
});
handleChange(value) {
this.setState({
schemaCode: value
});
try {
const schema = JSON.parse(value);
this.setState({
schema
});
} catch (e) {
//ignore
}
}
handleMouseUp() {
this.removeWindowEvents();
}
handleMouseDown(e) {
this.startX = e.clientX;
this.startWidth = this.state.asideWidth;
removeWindowEvents() {
window.removeEventListener('mouseup', this.handleMouseUp);
window.removeEventListener('mousemove', this.handleMouseMove);
}
// this.startPosition.y = e.clientY;
renderEditor() {
return (
<CodeEditor
value={this.state.schemaCode}
onChange={this.handleChange}
language="json"
/>
);
}
window.addEventListener('mouseup', this.handleMouseUp);
window.addEventListener('mousemove', this.handleMouseMove);
return false;
}
render() {
const {
vertical
} = this.props;
if (vertical) {
return (
<div className="vbox">
<div className="row-row">
<div className="cell pos-rlt">
<div className="scroll-y h-full pos-abt w-full">
{this.renderPreview()}
</div>
</div>
</div>
<div className="row-row" style={{height: 200}}>
<div className="cell">
{this.renderEditor()}
</div>
</div>
</div>
);
}
handleMouseMove(e) {
const diff = this.startX - e.clientX;
e.preventDefault();
return (
<div style={{
position: "absolute",
top: 50,
bottom: 0
}}>
<div className="hbox">
<div className="col pos-rlt">
<div className="scroll-y h-full pos-abt w-full">
{this.renderPreview()}
</div>
</div>
<div className="col bg-light lter b-l bg-auto pos-rlt" style={{width: this.state.asideWidth}}>
<div className="resizer" onMouseDown={this.handleMouseDown}></div>
{this.renderEditor()}
</div>
</div>
this.setState({
asideWidth: Math.min(800, Math.max(200, this.startWidth + diff))
});
}
handleMouseUp() {
this.removeWindowEvents();
}
removeWindowEvents() {
window.removeEventListener('mouseup', this.handleMouseUp);
window.removeEventListener('mousemove', this.handleMouseMove);
}
renderEditor() {
return (
<CodeEditor
value={this.state.schemaCode}
onChange={this.handleChange}
language="json"
/>
);
}
render() {
const {vertical} = this.props;
if (vertical) {
return (
<div className="vbox">
<div className="row-row">
<div className="cell pos-rlt">
<div className="scroll-y h-full pos-abt w-full">
{this.renderPreview()}
</div>
</div>
);
</div>
<div className="row-row" style={{height: 200}}>
<div className="cell">{this.renderEditor()}</div>
</div>
</div>
);
}
return (
<div
style={{
position: 'absolute',
top: 50,
bottom: 0
}}
>
<div className="hbox">
<div className="col pos-rlt">
<div className="scroll-y h-full pos-abt w-full">
{this.renderPreview()}
</div>
</div>
<div
className="col bg-light lter b-l bg-auto pos-rlt"
style={{width: this.state.asideWidth}}
>
<div className="resizer" onMouseDown={this.handleMouseDown} />
{this.renderEditor()}
</div>
</div>
</div>
);
}
}

View File

@ -3,187 +3,207 @@ import {render} from '../../src/index';
import axios from 'axios';
import {toast} from '../../src/components/Toast';
import {alert, confirm} from '../../src/components/Alert';
import Button from '../../src/components/Button'
import LazyComponent from '../../src/components/LazyComponent'
import {default as DrawerContainer} from '../../src/components/Drawer'
import { Portal } from 'react-overlays';
import Button from '../../src/components/Button';
import LazyComponent from '../../src/components/LazyComponent';
import {default as DrawerContainer} from '../../src/components/Drawer';
import {Portal} from 'react-overlays';
import {withRouter} from 'react-router';
function loadEditor() {
return new Promise((resolve) => require(['../../src/components/Editor'], (component) => resolve(component.default)));
return new Promise(resolve =>
require(['../../src/components/Editor'], component =>
resolve(component.default))
);
}
export default function(schema) {
if (!schema['$schema']) {
schema = {
'$schema': 'https://houtai.baidu.com/v2/schemas/page.json',
...schema
};
}
if (!schema['$schema']) {
schema = {
$schema: 'https://houtai.baidu.com/v2/schemas/page.json',
...schema
};
}
return withRouter(class extends React.Component {
static displayName = 'SchemaRenderer';
state = {open: false};
toggleCode = () => this.setState({
open: !this.state.open
return withRouter(
class extends React.Component {
static displayName = 'SchemaRenderer';
state = {open: false};
toggleCode = () =>
this.setState({
open: !this.state.open
});
close = () => this.setState({
open: false
close = () =>
this.setState({
open: false
});
constructor(props) {
super(props);
const {router} = props;
const normalizeLink = (to) => {
to = to || '';
const location = router.getCurrentLocation();
constructor(props) {
super(props);
const {router} = props;
const normalizeLink = to => {
to = to || '';
const location = router.getCurrentLocation();
if (to && to[0] === '#') {
to = location.pathname + location.search + to;
} else if (to && to[0] === '?') {
to = location.pathname + to;
}
if (to && to[0] === '#') {
to = location.pathname + location.search + to;
} else if (to && to[0] === '?') {
to = location.pathname + to;
}
const idx = to.indexOf('?');
const idx2 = to.indexOf('#');
let pathname = ~idx ? to.substring(0, idx) : ~idx2 ? to.substring(0, idx2) : to;
let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
let hash = ~idx2 ? to.substring(idx2) : '';
if (!pathname) {
pathname = location.pathname;
} else if (pathname[0] != '/' && !/^https?:\/\//.test(pathname)) {
let relativeBase = location.pathname;
const paths = relativeBase.split('/');
paths.pop();
let m;
while ((m = /^\.\.?\//.exec(pathname))) {
if (m[0] === '../') {
paths.pop();
}
pathname = pathname.substring(m[0].length);
}
pathname = paths.concat(pathname).join('/');
}
return pathname + search + hash;
const idx = to.indexOf('?');
const idx2 = to.indexOf('#');
let pathname = ~idx
? to.substring(0, idx)
: ~idx2
? to.substring(0, idx2)
: to;
let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
let hash = ~idx2 ? to.substring(idx2) : '';
if (!pathname) {
pathname = location.pathname;
} else if (pathname[0] != '/' && !/^https?:\/\//.test(pathname)) {
let relativeBase = location.pathname;
const paths = relativeBase.split('/');
paths.pop();
let m;
while ((m = /^\.\.?\//.exec(pathname))) {
if (m[0] === '../') {
paths.pop();
}
pathname = pathname.substring(m[0].length);
}
this.env = {
updateLocation: (location, replace) => {
router[replace ? 'replace' : 'push'](normalizeLink(location));
},
isCurrentUrl: (to) => {
const link = normalizeLink(to);
return router.isActive(link);
},
jumpTo: (to) => {
to = normalizeLink(to);
if (/^https?:\/\//.test(to)) {
window.location.replace(to);
} else {
router.push(to);
}
},
fetcher: ({
url,
method,
data,
config
}) => {
if (data && data instanceof FormData) {
// config.headers = config.headers || {};
// config.headers['Content-Type'] = 'multipart/form-data';
} else if (data
&& typeof data !== 'string'
&& !(data instanceof Blob)
&& !(data instanceof ArrayBuffer)
) {
data = JSON.stringify(data);
config = config || {};
config.headers = config.headers || {};
config.headers['Content-Type'] = 'application/json';
}
pathname = paths.concat(pathname).join('/');
}
if (method !== 'post' && method !== 'put' && method !== 'patch') {
if (data) {
if (method === 'delete') {
config.data = data;
} else {
config.params = data;
}
}
return pathname + search + hash;
};
this.env = {
updateLocation: (location, replace) => {
router[replace ? 'replace' : 'push'](normalizeLink(location));
},
isCurrentUrl: to => {
const link = normalizeLink(to);
return router.isActive(link);
},
jumpTo: to => {
to = normalizeLink(to);
return axios[method](url, config);
}
if (/^https?:\/\//.test(to)) {
window.location.replace(to);
} else {
router.push(to);
}
},
fetcher: ({url, method, data, config}) => {
if (data && data instanceof FormData) {
// config.headers = config.headers || {};
// config.headers['Content-Type'] = 'multipart/form-data';
} else if (
data &&
typeof data !== 'string' &&
!(data instanceof Blob) &&
!(data instanceof ArrayBuffer)
) {
data = JSON.stringify(data);
config = config || {};
config.headers = config.headers || {};
config.headers['Content-Type'] = 'application/json';
}
return axios[method](url, data, config);
},
isCancel: value => axios.isCancel(value),
notify: (type, msg) => toast[type] ? toast[type](msg, type === 'error' ? '系统错误' : '系统消息') : console.warn('[Notify]', type, msg),
alert,
confirm,
copy: (content) => console.log('Copy', content)
};
if (method !== 'post' && method !== 'put' && method !== 'patch') {
if (data) {
if (method === 'delete') {
config.data = data;
} else {
config.params = data;
}
}
this.handleEditorMount = this.handleEditorMount.bind(this);
}
return axios[method](url, config);
}
handleEditorMount(editor, monaco) {
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
enableSchemaRequest: true,
validate: true
});
}
return axios[method](url, data, config);
},
isCancel: value => axios.isCancel(value),
notify: (type, msg) =>
toast[type]
? toast[type](msg, type === 'error' ? '系统错误' : '系统消息')
: console.warn('[Notify]', type, msg),
alert,
confirm,
copy: content => console.log('Copy', content)
};
renderCode() {
return (
<LazyComponent
getComponent={loadEditor}
editorDidMount={this.handleEditorMount}
language="json"
value={schema}
placeholder="加载中,请稍后。。。"
disabled
/>
);
}
this.handleEditorMount = this.handleEditorMount.bind(this);
}
renderSchema() {
const {
router,
location,
theme
} = this.props;
handleEditorMount(editor, monaco) {
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
enableSchemaRequest: true,
validate: true
});
}
return render(schema, {
location,
theme
}, this.env);
}
renderCode() {
return (
<LazyComponent
getComponent={loadEditor}
editorDidMount={this.handleEditorMount}
language="json"
value={schema}
placeholder="加载中,请稍后。。。"
disabled
/>
);
}
render() {
const ns = this.props.classPrefix;
const showCode = this.props.showCode;
return (
<div className="schema-wrapper">
{showCode !== false ? (
<DrawerContainer
classPrefix={ns}
size="lg"
onHide={this.close}
show={this.state.open}
position="left"
>
{this.state.open ? this.renderCode() : null}
</DrawerContainer>
) : null }
{this.renderSchema()}
{showCode !== false ? (
<Portal container={() => document.querySelector('.navbar-nav')}>
<Button classPrefix={ns} onClick={this.toggleCode} active={this.state.open} iconOnly tooltip="查看源码" level="link" placement="bottom" className="view-code"><i className="fa fa-code" /></Button>
</Portal>
) : null}
</div>
);
}
});
renderSchema() {
const {router, location, theme} = this.props;
return render(
schema,
{
location,
theme
},
this.env
);
}
render() {
const ns = this.props.classPrefix;
const showCode = this.props.showCode;
return (
<div className="schema-wrapper">
{showCode !== false ? (
<DrawerContainer
classPrefix={ns}
size="lg"
onHide={this.close}
show={this.state.open}
position="left"
>
{this.state.open ? this.renderCode() : null}
</DrawerContainer>
) : null}
{this.renderSchema()}
{showCode !== false ? (
<Portal container={() => document.querySelector('.navbar-nav')}>
<Button
classPrefix={ns}
onClick={this.toggleCode}
active={this.state.open}
iconOnly
tooltip="查看源码"
level="link"
placement="bottom"
className="view-code"
>
<i className="fa fa-code" />
</Button>
</Portal>
) : null}
</div>
);
}
}
);
}

View File

@ -2,89 +2,93 @@ import React from 'react';
import TitleBar from '../../../src/components/TitleBar';
import {render} from '../../../src/index';
export default class SdkTest extends React.Component {
state = {
data: {
name: 'Amis Renderer',
id: 1,
email: 'xxx@xxx.com'
}
};
renderForm() {
return render({
title: '',
type: 'form',
controls: [
{
type: 'text',
name: 'name',
label: 'Name'
},
{
type: 'text',
name: 'id',
label: 'Id'
},
{
type: 'email',
name: 'email',
label: 'Email'
},
{
type: 'static',
label: '最后更新时间',
name: 'lastModified'
}
]
}, {
data: this.state.data,
onFailed: (reason, errors) => {
console.log('Submit Failed', errors, '\n', reason);
},
onSubmit: (values) => {
console.log('Submit', values);
},
onChange: (values, diff) => {
this.setState({
data: {
...values,
lastModified: new Date()
}
});
console.log('Diff', diff);
},
});
state = {
data: {
name: 'Amis Renderer',
id: 1,
email: 'xxx@xxx.com'
}
};
handleClick = () => {
this.setState({
renderForm() {
return render(
{
title: '',
type: 'form',
controls: [
{
type: 'text',
name: 'name',
label: 'Name'
},
{
type: 'text',
name: 'id',
label: 'Id'
},
{
type: 'email',
name: 'email',
label: 'Email'
},
{
type: 'static',
label: '最后更新时间',
name: 'lastModified'
}
]
},
{
data: this.state.data,
onFailed: (reason, errors) => {
console.log('Submit Failed', errors, '\n', reason);
},
onSubmit: values => {
console.log('Submit', values);
},
onChange: (values, diff) => {
this.setState({
data: {
name: 'Amis Renderer',
id: Math.round(Math.random() * 1000),
email: 'xxx@xxx.com'
...values,
lastModified: new Date()
}
})
};
});
render() {
return (
<div>
<TitleBar title="API 调用 集成在你的 React 应用中" />
<div className="wrapper">
{this.renderForm()}
console.log('Diff', diff);
}
}
);
}
<button onClick={this.handleClick}>随机修改</button>
handleClick = () => {
this.setState({
data: {
name: 'Amis Renderer',
id: Math.round(Math.random() * 1000),
email: 'xxx@xxx.com'
}
});
};
<h3>当前值</h3>
<pre><code>{JSON.stringify(this.state.data, null, 2)}</code></pre>
</div>
</div>
);
}
render() {
return (
<div>
<TitleBar title="API 调用 集成在你的 React 应用中" />
<div className="wrapper">
{this.renderForm()}
<button onClick={this.handleClick}>随机修改</button>
<h3>当前值</h3>
<pre>
<code>{JSON.stringify(this.state.data, null, 2)}</code>
</pre>
</div>
</div>
);
}
}

View File

@ -1,118 +1,118 @@
export default {
type: 'page',
title: '动态加载数据',
body: [
'<span class="text-danger">除了用 Page、CRUD、Form 或者 Wizard 能拉取数据外,还可以通过 Service 专门拉取数据,然后丢给其他类型的渲染器渲染。</span>',
type: 'page',
title: '动态加载数据',
body: [
'<span class="text-danger">除了用 Page、CRUD、Form 或者 Wizard 能拉取数据外,还可以通过 Service 专门拉取数据,然后丢给其他类型的渲染器渲染。</span>',
{
type: 'form',
title: '条件输入',
className: 'm-t',
wrapWithPanel: false,
target: 'service1',
mode: 'inline',
controls: [
{
type: 'text',
name: 'keywords',
placeholder: '关键字',
addOn: {
type: 'button',
icon: 'fa fa-search',
actionType: 'submit',
level: 'primary'
}
}
]
},
{
name: 'service1',
type: 'service',
className: 'm-t',
api: '/api/mock2/service/data?keywords=${keywords}',
body: [
'当前关键字是 ${keywords},当前时间是: ${date|date:YYYY-MM-DD HH\\:mm}',
{
type: 'form',
title: '条件输入',
className: 'm-t',
wrapWithPanel: false,
target: 'service1',
mode: 'inline',
controls: [
{
type: 'text',
name: 'keywords',
placeholder: '关键字',
addOn: {
type: 'button',
icon: 'fa fa-search',
actionType: 'submit',
level: 'primary'
}
}
]
type: 'table',
className: 'm-t',
source: '${table1}',
columns: [
{
name: 'id',
label: 'ID',
type: 'text'
},
{
name: 'text',
label: '文本',
type: 'text'
},
{
type: 'image',
label: '图片',
name: 'image',
popOver: {
title: '查看大图',
body:
'<div class="w-xxl"><img class="w-full" src="${image}"/></div>'
}
},
{
name: 'date',
type: 'date',
label: '日期'
}
]
},
{
name: 'service1',
type: 'service',
className: 'm-t',
api: '/api/mock2/service/data?keywords=${keywords}',
body: [
'当前关键字是 ${keywords},当前时间是: ${date|date:YYYY-MM-DD HH\\:mm}',
type: 'table',
source: '${table2}',
columns: [
{
name: 'progress',
label: '进度',
type: 'progress'
},
{
name: 'boolean',
label: '状态',
type: 'status'
},
{
name: 'boolean',
label: '开关',
type: 'switch'
// readOnly: false //
},
{
name: 'type',
label: '映射',
type: 'mapping',
map: {
'*': '其他:${type}',
'1': "<span class='label label-info'>漂亮</span>",
'2': "<span class='label label-success'>开心</span>",
'3': "<span class='label label-danger'>惊吓</span>",
'4': "<span class='label label-warning'>紧张</span>"
}
},
{
type: 'table',
className: 'm-t',
source: '${table1}',
columns: [
{
name: "id",
label: "ID",
type: "text"
},
{
name: "text",
label: "文本",
type: "text"
},
{
type: 'image',
label: '图片',
name: 'image',
popOver: {
title: '查看大图',
body: '<div class="w-xxl"><img class="w-full" src="${image}"/></div>'
}
},
{
name: 'date',
type: 'date',
label: '日期'
}
]
},
{
type: 'table',
source: '${table2}',
columns: [
{
name: "progress",
label: "进度",
type: "progress"
},
{
name: "boolean",
label: "状态",
type: "status"
},
{
name: "boolean",
label: "开关",
type: "switch",
// readOnly: false //
},
{
name: "type",
label: "映射",
type: "mapping",
map: {
"*": "其他:${type}",
"1": "<span class='label label-info'>漂亮</span>",
"2": "<span class='label label-success'>开心</span>",
"3": "<span class='label label-danger'>惊吓</span>",
"4": "<span class='label label-warning'>紧张</span>"
}
},
{
name: 'list',
type: 'list',
label: 'List',
placeholder: '-',
listItem: {
title: '${title}',
subTitle: '${description}'
}
}
]
}
]
{
name: 'list',
type: 'list',
label: 'List',
placeholder: '-',
listItem: {
title: '${title}',
subTitle: '${description}'
}
}
]
}
]
}
]
}
]
};

View File

@ -1,68 +1,68 @@
export default {
type: 'page',
title: '动态加载表单中的部分',
body: [
'<span class="text-danger">同样通过 <code>service</code>的<code>schemaApi</code> 来加载部分内容,当然也可以全部由它来加载</span>',
type: 'page',
title: '动态加载表单中的部分',
body: [
'<span class="text-danger">同样通过 <code>service</code>的<code>schemaApi</code> 来加载部分内容,当然也可以全部由它来加载</span>',
{
type: 'form',
panelClassName: 'Panel--info m-t',
target: 'service1',
mode: 'horizontal',
api: '/api/mock2/form/saveForm?waitSeconds=1',
fieldSet: [
{
title: '基本信息',
controls: [
{
type: 'text',
label: '字段一',
name: 'filed1'
},
{
type: 'text',
label: '字段二',
name: 'filed2'
}
]
},
{
type: 'form',
panelClassName: 'Panel--info m-t',
target: 'service1',
mode: 'horizontal',
api: '/api/mock2/form/saveForm?waitSeconds=1',
fieldSet: [
title: '其他信息',
controls: [
{
name: 'tpl',
type: 'select',
label: '模板',
inline: true,
required: true,
value: 'tpl1',
options: [
{
title: '基本信息',
controls: [
{
type: 'text',
label: '字段一',
name: 'filed1',
},
{
type: 'text',
label: '字段二',
name: 'filed2'
}
]
label: '模板1',
value: 'tpl1'
},
{
title: '其他信息',
controls: [
{
name: 'tpl',
type: 'select',
label: '模板',
inline: true,
required: true,
value: 'tpl1',
options: [
{
label: '模板1',
value: 'tpl1'
},
{
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
]
},
{
type: 'service',
className: 'm-t',
initFetchSchemaOn: 'data.tpl',
schemaApi: '/api/mock2/service/form?tpl=$tpl',
}
]
label: '模板2',
value: 'tpl2'
},
{
label: '模板3',
value: 'tpl3'
}
]
]
},
{
type: 'service',
className: 'm-t',
initFetchSchemaOn: 'data.tpl',
schemaApi: '/api/mock2/service/form?tpl=$tpl'
}
]
}
]
}
]
}
]
};

View File

@ -1,50 +1,50 @@
export default {
type: 'page',
title: '动态加载页面',
body: [
'<span class="text-danger">可以通过 <code>service</code>的<code>schemaApi</code> 动态控制内容。</span>',
type: 'page',
title: '动态加载页面',
body: [
'<span class="text-danger">可以通过 <code>service</code>的<code>schemaApi</code> 动态控制内容。</span>',
{
type: 'form',
title: '条件输入',
panelClassName: 'panel-info m-t',
target: 'service1',
mode: 'inline',
submitOnInit: true,
controls: [
{
type: 'form',
title: '条件输入',
panelClassName: 'panel-info m-t',
target: 'service1',
mode: 'inline',
submitOnInit: true,
controls: [
{
label: '加载页面类型',
required: true,
type: 'button-group',
submitOnChange: true,
value: 'crud',
name: 'type',
options: [
{
label: 'Crud',
value: 'crud'
},
label: '加载页面类型',
required: true,
type: 'button-group',
submitOnChange: true,
value: 'crud',
name: 'type',
options: [
{
label: 'Crud',
value: 'crud'
},
{
label: 'Form',
value: 'form'
},
{
label: 'Form',
value: 'form'
},
{
label: 'Tabs',
value: 'tabs'
}
]
}
]
},
{
name: 'service1',
type: 'service',
className: 'm-t',
initFetchSchema: false,
schemaApi: '/api/mock2/service/schema?type=$type',
{
label: 'Tabs',
value: 'tabs'
}
]
}
]
}
]
},
{
name: 'service1',
type: 'service',
className: 'm-t',
initFetchSchema: false,
schemaApi: '/api/mock2/service/schema?type=$type'
}
]
};

View File

@ -1,47 +1,48 @@
export default {
type: 'page',
title: '表单中选项卡分组',
subTitle: '',
body: [
'<p>多个 controls 可以通过 tabs 来分组展示,表单将作为一个整体提交。</p>',
type: 'page',
title: '表单中选项卡分组',
subTitle: '',
body: [
'<p>多个 controls 可以通过 tabs 来分组展示,表单将作为一个整体提交。</p>',
{
type: 'form',
title: '',
tabs: [
{
type: 'form',
title: '',
tabs: [
title: '选项卡1',
hash: 'tab1',
controls: [
{
title: '选项卡1',
hash: 'tab1',
controls: [
{
type: 'text',
label: '文本1',
name: 'a'
}
]
},
{
title: '选项卡2',
hash: 'tab2',
controls: [
{
type: 'text',
label: '文本2',
name: 'b'
}
]
},
{
title: '选项卡3',
hash: 'tab3',
controls: [
{
type: 'text',
label: '文本3',
name: 'c'
}
]
type: 'text',
label: '文本1',
name: 'a'
}
]
}]
}
]
},
{
title: '选项卡2',
hash: 'tab2',
controls: [
{
type: 'text',
label: '文本2',
name: 'b'
}
]
},
{
title: '选项卡3',
hash: 'tab3',
controls: [
{
type: 'text',
label: '文本3',
name: 'c'
}
]
}
]
}
]
};

View File

@ -1,165 +1,163 @@
export default {
type: 'page',
title: '选项卡示例',
subTitle: '所有选项卡都在当前页面中包括默认、line、card以及radio模式',
body: [
type: 'page',
title: '选项卡示例',
subTitle: '所有选项卡都在当前页面中包括默认、line、card以及radio模式',
body: [
{
type: 'tabs',
tabs: [
{
type: 'tabs',
tabs: [
{
title: '选项卡1',
hash: 'tab1',
body: '选项卡内容1'
},
title: '选项卡1',
hash: 'tab1',
body: '选项卡内容1'
},
{
title: '选项卡2',
hash: 'tab2',
body: {
type: 'form',
panelClassName: 'panel-primary',
controls: [
{
type: 'text',
name: 'a',
label: '文本'
}
]
}
},
{
title: '选项卡3',
body: {
type: "crud",
api: "/api/sample",
filter: {
title: "条件搜索",
submitText: "",
controls: [
{
type: "text",
name: "keywords",
placeholder: "通过关键字搜索",
clearable: true,
addOn: {
label: "搜索",
type: "submit"
}
},
{
type: "plain",
text: "这里的表单项可以配置多个"
}
]
},
columns: [
{
name: "id",
label: "ID",
width: 20
},
{
name: "engine",
label: "Rendering engine"
},
{
name: "browser",
label: "Browser"
},
{
name: "platform",
label: "Platform(s)"
},
{
name: "version",
label: "Engine version"
},
{
name: "grade",
label: "CSS grade"
},
{
type: "operation",
label: "操作",
width: 100,
buttons: [
]
}
]
}
}
{
title: '选项卡2',
hash: 'tab2',
body: {
type: 'form',
panelClassName: 'panel-primary',
controls: [
{
type: 'text',
name: 'a',
label: '文本'
}
]
}
},
{
type: 'divider'
},
{
type: 'tabs',
mode: 'line',
tabs: [
{
title: '选项卡1',
body: '选项卡内容1'
},
{
title: '选项卡3',
body: {
type: 'crud',
api: '/api/sample',
filter: {
title: '条件搜索',
submitText: '',
controls: [
{
title: '选项卡2',
body: '选项卡内容2'
type: 'text',
name: 'keywords',
placeholder: '通过关键字搜索',
clearable: true,
addOn: {
label: '搜索',
type: 'submit'
}
},
{
title: '选项卡3',
body: '选项卡内容3'
type: 'plain',
text: '这里的表单项可以配置多个'
}
]
},
columns: [
{
name: 'id',
label: 'ID',
width: 20
},
{
name: 'engine',
label: 'Rendering engine'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'platform',
label: 'Platform(s)'
},
{
name: 'version',
label: 'Engine version'
},
{
name: 'grade',
label: 'CSS grade'
},
{
type: 'operation',
label: '操作',
width: 100,
buttons: []
}
]
},
}
}
]
},
{
type: 'divider'
},
{
type: 'tabs',
mode: 'line',
tabs: [
{
type: 'divider'
title: '选项卡1',
body: '选项卡内容1'
},
{
type: 'tabs',
mode: 'card',
tabs: [
{
title: '选项卡1',
body: '选项卡内容1'
},
{
title: '选项卡2',
body: '选项卡内容2'
},
{
title: '选项卡3',
body: '选项卡内容3'
}
]
title: '选项卡2',
body: '选项卡内容2'
},
{
type: 'divider'
},
title: '选项卡3',
body: '选项卡内容3'
}
]
},
{
type: 'divider'
},
{
type: 'tabs',
mode: 'card',
tabs: [
{
type: 'tabs',
mode: 'radio',
tabs: [
{
title: '选项卡1',
body: '选项卡内容1'
},
{
title: '选项卡2',
body: '选项卡内容2'
},
{
title: '选项卡3',
body: '选项卡内容3'
}
]
title: '选项卡1',
body: '选项卡内容1'
},
]
}
{
title: '选项卡2',
body: '选项卡内容2'
},
{
title: '选项卡3',
body: '选项卡内容3'
}
]
},
{
type: 'divider'
},
{
type: 'tabs',
mode: 'radio',
tabs: [
{
title: '选项卡1',
body: '选项卡内容1'
},
{
title: '选项卡2',
body: '选项卡内容2'
},
{
title: '选项卡3',
body: '选项卡内容3'
}
]
}
]
};

View File

@ -1,35 +1,35 @@
export default {
type: 'page',
title: '选项卡1页面',
body: [
'<p>也可以多个页面,利用导航<code>nav</code>渲染期模拟 tabs 的效果。这样可以让 url 更加友好,而不是只能用 hash。</p>',
type: 'page',
title: '选项卡1页面',
body: [
'<p>也可以多个页面,利用导航<code>nav</code>渲染期模拟 tabs 的效果。这样可以让 url 更加友好,而不是只能用 hash。</p>',
{
type: 'nav',
links: [
{
type: 'nav',
links: [
{
label: '选项卡1',
icon: 'fa fa-cloud',
to: './tab1'
},
{
label: '选项卡2',
to: './tab2'
},
{
label: '选项卡3',
icon: 'fa fa-youtube',
to: './tab3'
}
]
label: '选项卡1',
icon: 'fa fa-cloud',
to: './tab1'
},
{
type: 'wrapper',
className: 'wrapper bg-white b-l b-b b-r',
body: '选项卡1的内容'
label: '选项卡2',
to: './tab2'
},
{
label: '选项卡3',
icon: 'fa fa-youtube',
to: './tab3'
}
]
}
]
},
{
type: 'wrapper',
className: 'wrapper bg-white b-l b-b b-r',
body: '选项卡1的内容'
}
]
};

View File

@ -1,35 +1,35 @@
export default {
type: 'page',
title: '选项卡2页面',
body: [
'<p>也可以多个页面,利用导航<code>nav</code>渲染期模拟 tabs 的效果。</p>',
type: 'page',
title: '选项卡2页面',
body: [
'<p>也可以多个页面,利用导航<code>nav</code>渲染期模拟 tabs 的效果。</p>',
{
type: 'nav',
links: [
{
type: 'nav',
links: [
{
label: '选项卡1',
icon: 'fa fa-cloud',
to: './tab1'
},
{
label: '选项卡2',
to: './tab2'
},
{
label: '选项卡3',
icon: 'fa fa-youtube',
to: './tab3'
}
]
label: '选项卡1',
icon: 'fa fa-cloud',
to: './tab1'
},
{
type: 'wrapper',
className: 'wrapper bg-white b-l b-b b-r',
body: '选项卡2的内容'
label: '选项卡2',
to: './tab2'
},
{
label: '选项卡3',
icon: 'fa fa-youtube',
to: './tab3'
}
]
}
]
},
{
type: 'wrapper',
className: 'wrapper bg-white b-l b-b b-r',
body: '选项卡2的内容'
}
]
};

View File

@ -1,121 +1,83 @@
export default {
type: 'page',
title: '选项卡3页面',
body: [
'<p>也可以多个页面,利用导航<code>nav</code>渲染期模拟 tabs 的效果。</p>',
type: 'page',
title: '选项卡3页面',
body: [
'<p>也可以多个页面,利用导航<code>nav</code>渲染期模拟 tabs 的效果。</p>',
{
type: 'nav',
links: [
{
type: 'nav',
links: [
{
label: '选项卡1',
icon: 'fa fa-cloud',
to: './tab1'
},
{
label: '选项卡2',
to: './tab2'
},
{
label: '选项卡3',
icon: 'fa fa-youtube',
to: './tab3'
}
]
label: '选项卡1',
icon: 'fa fa-cloud',
to: './tab1'
},
{
type: 'wrapper',
className: 'wrapper bg-white b-l b-b b-r',
body: {
"type": "chart",
"config": {
"title": {
"text": "极坐标双数值轴"
},
"legend": {
"data": [
"line"
]
},
"polar": {
"center": [
"50%",
"54%"
]
},
"tooltip": {
"trigger": "axis",
"axisPointer": {
"type": "cross"
}
},
"angleAxis": {
"type": "value",
"startAngle": 0
},
"radiusAxis": {
"min": 0
},
"series": [
{
"coordinateSystem": "polar",
"name": "line",
"type": "line",
"showSymbol": false,
"data": [
[
0,
0
],
[
0.03487823687206265,
1
],
[
0.06958655048003272,
2
],
[
0.10395584540887964,
3
],
[
0.13781867790849958,
4
],
[
0.17101007166283433,
5
],
[
0.2033683215379001,
6
],
[
0.2347357813929454,
7
],
[
0.26495963211660245,
8
],
[
0.2938926261462365,
9
],
[
0.3213938048432697,
10
]
]
}
],
"animationDuration": 2000
}
}
label: '选项卡2',
to: './tab2'
},
{
label: '选项卡3',
icon: 'fa fa-youtube',
to: './tab3'
}
]
}
]
},
{
type: 'wrapper',
className: 'wrapper bg-white b-l b-b b-r',
body: {
type: 'chart',
config: {
title: {
text: '极坐标双数值轴'
},
legend: {
data: ['line']
},
polar: {
center: ['50%', '54%']
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
angleAxis: {
type: 'value',
startAngle: 0
},
radiusAxis: {
min: 0
},
series: [
{
coordinateSystem: 'polar',
name: 'line',
type: 'line',
showSymbol: false,
data: [
[0, 0],
[0.03487823687206265, 1],
[0.06958655048003272, 2],
[0.10395584540887964, 3],
[0.13781867790849958, 4],
[0.17101007166283433, 5],
[0.2033683215379001, 6],
[0.2347357813929454, 7],
[0.26495963211660245, 8],
[0.2938926261462365, 9],
[0.3213938048432697, 10]
]
}
],
animationDuration: 2000
}
}
}
]
};

View File

@ -1,36 +1,37 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "异步任务",
"body": [
'<p class="text-danger"></p>',
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '异步任务',
body: [
'<p class="text-danger"></p>',
{
type: 'tasks',
name: 'tasks',
items: [
{
"type": "tasks",
"name": "tasks",
"items": [
{
"label": "hive 任务",
"key": "hive",
"status": 4,
"remark": "查看详情<a target=\"_blank\" href=\"http://www.baidu.com\">日志</a>。"
},
{
"label": "小流量",
"key": "partial",
"status": 4
},
{
"label": "全量",
"key": "full",
"status": 4
}
]
label: 'hive 任务',
key: 'hive',
status: 4,
remark:
'查看详情<a target="_blank" href="http://www.baidu.com">日志</a>。'
},
{
"type": "tasks",
"name": "tasks",
"className": "b-a bg-white table-responsive m-t",
"checkApi": "/api/mock2/task"
label: '小流量',
key: 'partial',
status: 4
},
{
label: '全量',
key: 'full',
status: 4
}
]
}
]
},
{
type: 'tasks',
name: 'tasks',
className: 'b-a bg-white table-responsive m-t',
checkApi: '/api/mock2/task'
}
]
};

View File

@ -1,46 +1,77 @@
import React from 'react';
import Button from '../../src/components/Button';
export default class TestComponent extends React.Component {
render() {
return (
<div className="wrapper">
<div className="m-b">
<Button className="m-r-xs" classPrefix="cxd-">按钮</Button>
render() {
return (
<div className="wrapper">
<div className="m-b">
<Button className="m-r-xs" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" level="primary" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" level="primary" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" level="secondary" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" level="secondary" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" level="success" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" level="success" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" level="info" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" level="info" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" level="warning" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" level="warning" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" level="danger" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" level="danger" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" level="light" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" level="light" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" level="dark" classPrefix="cxd-">按钮</Button>
</div>
<Button className="m-r-xs" level="dark" classPrefix="cxd-">
按钮
</Button>
</div>
<div className="m-b">
<div className="m-b">
<Button className="m-r-xs" size="xs" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" size="sm" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" size="md" classPrefix="cxd-">
按钮
</Button>
<Button className="m-r-xs" size="lg" classPrefix="cxd-">
按钮
</Button>
</div>
<Button className="m-r-xs" size="xs" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" size="sm" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" size="md" classPrefix="cxd-">按钮</Button>
<Button className="m-r-xs" size="lg" classPrefix="cxd-">按钮</Button>
</div>
<div className="m-b">
<Button className="m-r-xs" classPrefix="cxd-"><i className="fa fa-cloud"/><span>按钮</span></Button>
<Button className="m-r-xs" classPrefix="cxd-"><span>按钮</span><i className="fa fa-cloud"/></Button>
<Button className="m-r-xs" classPrefix="cxd-" iconOnly><i className="fa fa-cloud"/></Button>
</div>
</div>
)
}
}
<div className="m-b">
<Button className="m-r-xs" classPrefix="cxd-">
<i className="fa fa-cloud" />
<span>按钮</span>
</Button>
<Button className="m-r-xs" classPrefix="cxd-">
<span>按钮</span>
<i className="fa fa-cloud" />
</Button>
<Button className="m-r-xs" classPrefix="cxd-" iconOnly>
<i className="fa fa-cloud" />
</Button>
</div>
</div>
);
}
}

View File

@ -1,14 +1,14 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "视频播放器",
"body": [
'<p class="text-danger">另外还支持直播流, flv 和 hls 格式</p>',
{
"type": "video",
"autoPlay": false,
"rates": [1.0, 1.5, 2.0],
"src": "https://media.w3.org/2010/05/sintel/trailer_hd.mp4",
"poster": "https://video-react.js.org/assets/poster.png"
}
]
}
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '视频播放器',
body: [
'<p class="text-danger">另外还支持直播流, flv 和 hls 格式</p>',
{
type: 'video',
autoPlay: false,
rates: [1.0, 1.5, 2.0],
src: 'https://media.w3.org/2010/05/sintel/trailer_hd.mp4',
poster: 'https://video-react.js.org/assets/poster.png'
}
]
};

View File

@ -1,148 +1,142 @@
export default {
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
"title": "表单向导",
"body": [
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
title: '表单向导',
body: [
{
type: 'wizard',
api: '/api/mock2/form/saveForm?waitSeconds=2',
initApi: '/api/mock2/form/initData?waitSeconds=2',
steps: [
{
"type": "wizard",
"api": "/api/mock2/form/saveForm?waitSeconds=2",
"initApi": "/api/mock2/form/initData?waitSeconds=2",
"steps": [
{
"title": "第一步",
"controls": [
{
"name": "website",
"label": "网址",
"type": "url",
"required": true
},
{
"name": "name",
"label": "名称",
"type": "text",
"required": true
}
]
},
{
"title": "Step 2",
"controls": [
{
"name": "email2",
"label": "邮箱",
"type": "email",
"required": true
}
]
},
{
"title": "Step 3",
"controls": [
"这是最后一步了"
]
}
]
title: '第一步',
controls: [
{
name: 'website',
label: '网址',
type: 'url',
required: true
},
{
name: 'name',
label: '名称',
type: 'text',
required: true
}
]
},
{
"type": "wizard",
"api": "/api/mock2/form/saveForm?waitSeconds=2",
"mode": "vertical",
"steps": [
{
"title": "第一步",
"controls": [
{
"name": "website",
"label": "网址",
"type": "url",
"required": true
},
{
"name": "email",
"label": "邮箱",
"type": "email",
"required": true
}
]
},
{
"title": "Step 2",
"controls": [
{
"name": "email2",
"label": "邮箱",
"type": "email",
"required": true
}
]
},
{
"title": "Step 3",
"controls": [
"这是最后一步了"
]
}
]
title: 'Step 2',
controls: [
{
name: 'email2',
label: '邮箱',
type: 'email',
required: true
}
]
},
{
"type": "wizard",
"steps": [
{
"title": "第一步",
"controls": [
{
"name": "website",
"label": "网址",
"type": "url",
"required": true
},
{
"name": "email",
"label": "邮箱",
"type": "email",
"required": true
}
],
"api": "/api/mock2/form/saveForm?waitSeconds=2"
},
{
"title": "第二步",
"controls": [
{
"name": "test1",
"type": "email",
"label": "Email",
"value": "test@test.com"
},
{
"type": "divider"
},
{
"type": "text",
"name": "test2",
"label": "必填示例",
"required": true
},
{
"type": "divider"
},
{
"type": "text",
"name": "test3",
"placeholder": "可选"
}
],
"initApi": "/api/mock2/form/initForm",
"api": "/api/mock2/form/saveForm?waitSeconds=2"
},
{
"title": "确定",
"controls": [
"最后一步了,确认要提交吗?"
],
"api": "/api/mock2/form/saveForm?waitSeconds=2"
}
]
title: 'Step 3',
controls: ['这是最后一步了']
}
]
}
]
},
{
type: 'wizard',
api: '/api/mock2/form/saveForm?waitSeconds=2',
mode: 'vertical',
steps: [
{
title: '第一步',
controls: [
{
name: 'website',
label: '网址',
type: 'url',
required: true
},
{
name: 'email',
label: '邮箱',
type: 'email',
required: true
}
]
},
{
title: 'Step 2',
controls: [
{
name: 'email2',
label: '邮箱',
type: 'email',
required: true
}
]
},
{
title: 'Step 3',
controls: ['这是最后一步了']
}
]
},
{
type: 'wizard',
steps: [
{
title: '第一步',
controls: [
{
name: 'website',
label: '网址',
type: 'url',
required: true
},
{
name: 'email',
label: '邮箱',
type: 'email',
required: true
}
],
api: '/api/mock2/form/saveForm?waitSeconds=2'
},
{
title: '第二步',
controls: [
{
name: 'test1',
type: 'email',
label: 'Email',
value: 'test@test.com'
},
{
type: 'divider'
},
{
type: 'text',
name: 'test2',
label: '必填示例',
required: true
},
{
type: 'divider'
},
{
type: 'text',
name: 'test3',
placeholder: '可选'
}
],
initApi: '/api/mock2/form/initForm',
api: '/api/mock2/form/saveForm?waitSeconds=2'
},
{
title: '确定',
controls: ['最后一步了,确认要提交吗?'],
api: '/api/mock2/form/saveForm?waitSeconds=2'
}
]
}
]
};

View File

@ -1,208 +1,229 @@
import './polyfills/index';
import React from 'react';
import { render as renderReact } from 'react-dom';
import {render as renderReact} from 'react-dom';
import axios from 'axios';
import copy from 'copy-to-clipboard';
import qs from 'qs';
import {
toast,
alert,
confirm,
ToastComponent,
AlertComponent,
render as renderAmis
toast,
alert,
confirm,
ToastComponent,
AlertComponent,
render as renderAmis
} from '../src/index';
export function embed(container: string | HTMLElement, schema: any, data: any, env: any) {
if (typeof container === 'string') {
container = document.querySelector(container) as HTMLElement;
}
if (!container) {
console.error('选择器不对,页面上没有此元素');
return;
} else if (container.tagName === 'BODY') {
let div = document.createElement('div');
container.appendChild(div);
container = div;
}
container.classList.add('amis-scope');
let scoped:any;
const normalizeLink = (to:string) => {
to = to || '';
const location = window.location;
export function embed(
container: string | HTMLElement,
schema: any,
data: any,
env: any
) {
if (typeof container === 'string') {
container = document.querySelector(container) as HTMLElement;
}
if (!container) {
console.error('选择器不对,页面上没有此元素');
return;
} else if (container.tagName === 'BODY') {
let div = document.createElement('div');
container.appendChild(div);
container = div;
}
container.classList.add('amis-scope');
let scoped: any;
const normalizeLink = (to: string) => {
to = to || '';
const location = window.location;
if (to && to[0] === '#') {
to = location.pathname + location.search + to;
} else if (to && to[0] === '?') {
to = location.pathname + to;
}
const idx = to.indexOf('?');
const idx2 = to.indexOf('#');
let pathname = ~idx ? to.substring(0, idx) : ~idx2 ? to.substring(0, idx2) : to;
let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
let hash = ~idx2 ? to.substring(idx2) : '';
if (!pathname) {
pathname = location.pathname;
} else if (pathname[0] != '/' && !/^https?\:\/\//.test(pathname)) {
let relativeBase = location.pathname;
const paths = relativeBase.split('/');
paths.pop();
let m;
while ((m = /^\.\.?\//.exec(pathname))) {
if (m[0] === '../') {
paths.pop();
}
pathname = pathname.substring(m[0].length);
}
pathname = paths.concat(pathname).join('/');
}
return pathname + search + hash;
if (to && to[0] === '#') {
to = location.pathname + location.search + to;
} else if (to && to[0] === '?') {
to = location.pathname + to;
}
const responseAdpater = (api:any) => (value:any) => {
let response = value.data;
if (env && env.responseAdpater) {
const url = api.url;
const idx = api.url.indexOf('?');
const query = ~idx ? qs.parse(api.url.substring(idx)) : {};
const request = {
...api,
query: query,
body: api.data
};
response = env.responseAdpater(api, response, query, request);
} else {
if (response.hasOwnProperty('errno')) {
response.status = response.errno;
response.msg = response.errmsg;
} else if (response.hasOwnProperty('no')) {
response.status = response.no;
response.msg = response.error;
}
}
const idx = to.indexOf('?');
const idx2 = to.indexOf('#');
let pathname = ~idx
? to.substring(0, idx)
: ~idx2
? to.substring(0, idx2)
: to;
let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
let hash = ~idx2 ? to.substring(idx2) : '';
const result = {
...value,
data: response
if (!pathname) {
pathname = location.pathname;
} else if (pathname[0] != '/' && !/^https?\:\/\//.test(pathname)) {
let relativeBase = location.pathname;
const paths = relativeBase.split('/');
paths.pop();
let m;
while ((m = /^\.\.?\//.exec(pathname))) {
if (m[0] === '../') {
paths.pop();
}
return result;
pathname = pathname.substring(m[0].length);
}
pathname = paths.concat(pathname).join('/');
}
return pathname + search + hash;
};
const responseAdpater = (api: any) => (value: any) => {
let response = value.data;
if (env && env.responseAdpater) {
const url = api.url;
const idx = api.url.indexOf('?');
const query = ~idx ? qs.parse(api.url.substring(idx)) : {};
const request = {
...api,
query: query,
body: api.data
};
response = env.responseAdpater(api, response, query, request);
} else {
if (response.hasOwnProperty('errno')) {
response.status = response.errno;
response.msg = response.errmsg;
} else if (response.hasOwnProperty('no')) {
response.status = response.no;
response.msg = response.error;
}
}
const result = {
...value,
data: response
};
return result;
};
renderReact((
<div className="amis-routes-wrapper">
<ToastComponent position={env && env.toastPosition || 'top-right'} closeButton={false} timeOut={5000} extendedTimeOut={3000}/>
<AlertComponent container={container} />
renderReact(
<div className="amis-routes-wrapper">
<ToastComponent
position={(env && env.toastPosition) || 'top-right'}
closeButton={false}
timeOut={5000}
extendedTimeOut={3000}
/>
<AlertComponent container={container} />
{renderAmis(schema, {
...data,
scopeRef: (ref:any) => scoped = ref
}, {
getModalContainer: () => document.querySelector('.amis-scope'),
notify: (type: string, msg: string) => toast[type] ? toast[type](msg, type === 'error' ? '系统错误' : '系统消息') : console.warn('[Notify]', type, msg),
alert,
confirm,
updateLocation: (to:any, replace:boolean) => {
if (to === 'goBack') {
return window.history.back();
}
{renderAmis(
schema,
{
...data,
scopeRef: (ref: any) => (scoped = ref)
},
{
getModalContainer: () => document.querySelector('.amis-scope'),
notify: (type: string, msg: string) =>
toast[type]
? toast[type](msg, type === 'error' ? '系统错误' : '系统消息')
: console.warn('[Notify]', type, msg),
alert,
confirm,
updateLocation: (to: any, replace: boolean) => {
if (to === 'goBack') {
return window.history.back();
}
replace || (location.href = normalizeLink(to));
},
isCurrentUrl: (to:string) => {
const link = normalizeLink(to);
const location = window.location;
let pathname = link;
let search = '';
const idx = link.indexOf('?');
if (~idx) {
pathname = link.substring(0, idx);
search = link.substring(idx);
}
replace || (location.href = normalizeLink(to));
},
isCurrentUrl: (to: string) => {
const link = normalizeLink(to);
const location = window.location;
let pathname = link;
let search = '';
const idx = link.indexOf('?');
if (~idx) {
pathname = link.substring(0, idx);
search = link.substring(idx);
}
if (search) {
if (pathname !== location.pathname || !location.search) {
return false;
}
if (search) {
if (pathname !== location.pathname || !location.search) {
return false;
}
const query = qs.parse(search.substring(1));
const currentQuery = qs.parse(location.search.substring(1));
const query = qs.parse(search.substring(1));
const currentQuery = qs.parse(location.search.substring(1));
return Object.keys(query).every(key => query[key] === currentQuery[key]);
} else if (pathname === location.pathname) {
return true;
}
return Object.keys(query).every(
key => query[key] === currentQuery[key]
);
} else if (pathname === location.pathname) {
return true;
}
return false;
},
jumpTo: (to:string, action?:any) => {
if (to === 'goBack') {
return window.history.back();
}
return false;
},
jumpTo: (to: string, action?: any) => {
if (to === 'goBack') {
return window.history.back();
}
to = normalizeLink(to);
to = normalizeLink(to);
if (action && action.actionType === 'url') {
action.blank === false ? (window.location.href = to) : window.open(to);
return;
}
if (action && action.actionType === 'url') {
action.blank === false
? (window.location.href = to)
: window.open(to);
return;
}
if (/^https?:\/\//.test(to)) {
window.location.replace(to);
} else {
location.href = to;
}
},
fetcher: (api: any) => {
let {
url,
method,
data,
responseType,
config,
headers
} = api;
config = config || {};
config.withCredentials = true;
responseType && (config.responseType = responseType);
if (config.cancelExecutor) {
config.cancelToken = new (axios as any).CancelToken(config.cancelExecutor);
}
config.headers = headers || {};
config.method = method;
if (method === 'get' && data) {
config.params = data;
} else if (data && data instanceof FormData) {
// config.headers['Content-Type'] = 'multipart/form-data';
} else if (data
&& typeof data !== 'string'
&& !(data instanceof Blob)
&& !(data instanceof ArrayBuffer)
) {
data = JSON.stringify(data);
config.headers['Content-Type'] = 'application/json';
}
data && (config.data = data);
return axios(url, config)
.then(responseAdpater(api));
},
isCancel: (value: any) => (axios as any).isCancel(value),
copy: (contents: string, options: any = {}) => {
const ret = copy(contents, options);
ret && options.shutup !== true && toast.info('内容已拷贝到剪切板');
return ret;
},
richTextToken: '',
...env
})}
</div>
), container);
return scoped;
if (/^https?:\/\//.test(to)) {
window.location.replace(to);
} else {
location.href = to;
}
},
fetcher: (api: any) => {
let {url, method, data, responseType, config, headers} = api;
config = config || {};
config.withCredentials = true;
responseType && (config.responseType = responseType);
if (config.cancelExecutor) {
config.cancelToken = new (axios as any).CancelToken(
config.cancelExecutor
);
}
config.headers = headers || {};
config.method = method;
if (method === 'get' && data) {
config.params = data;
} else if (data && data instanceof FormData) {
// config.headers['Content-Type'] = 'multipart/form-data';
} else if (
data &&
typeof data !== 'string' &&
!(data instanceof Blob) &&
!(data instanceof ArrayBuffer)
) {
data = JSON.stringify(data);
config.headers['Content-Type'] = 'application/json';
}
data && (config.data = data);
return axios(url, config).then(responseAdpater(api));
},
isCancel: (value: any) => (axios as any).isCancel(value),
copy: (contents: string, options: any = {}) => {
const ret = copy(contents, options);
ret && options.shutup !== true && toast.info('内容已拷贝到剪切板');
return ret;
},
richTextToken: '',
...env
}
)}
</div>,
container
);
return scoped;
}

View File

@ -3,12 +3,9 @@
* @author liaoxuezhi@cloud.com
*/
import React from 'react';
import { render } from 'react-dom';
import {render} from 'react-dom';
import App from './components/App';
export function bootstrap(mountTo, initalState) {
render(
<App />,
mountTo
);
render(<App />, mountTo);
}

View File

@ -1,37 +1,36 @@
const __moduleId = (str: string) => '';
const mapping: {
[propName: string]: any;
[propName: string]: any;
} = {
'jquery': __moduleId('jquery'),
'react': __moduleId('react'),
'react-dom': __moduleId('react-dom'),
'react-addons-update': __moduleId('react-addons-update'),
'immutability-helper': __moduleId('react-addons-update'),
'react-cropper': __moduleId('react-cropper'),
'react-dropzone': __moduleId('react-dropzone'),
'classnames': __moduleId('classnames'),
'axios': __moduleId('axios'),
'moment': __moduleId('moment'),
'mobx': __moduleId('mobx'),
'mobx-state-tree': __moduleId('mobx-state-tree'),
'react-transition-group': __moduleId('react-transition-group'),
'echarts': __moduleId('echarts'),
'zrender': __moduleId('zrender'),
'sortablejs': __moduleId('sortablejs'),
'amis': __moduleId('../src'),
'amis/embed': __moduleId('./embed.tsx'),
'prop-types': __moduleId('prop-types'),
'async': __moduleId('async'),
'qs': __moduleId('qs')
jquery: __moduleId('jquery'),
react: __moduleId('react'),
'react-dom': __moduleId('react-dom'),
'react-addons-update': __moduleId('react-addons-update'),
'immutability-helper': __moduleId('react-addons-update'),
'react-cropper': __moduleId('react-cropper'),
'react-dropzone': __moduleId('react-dropzone'),
classnames: __moduleId('classnames'),
axios: __moduleId('axios'),
moment: __moduleId('moment'),
mobx: __moduleId('mobx'),
'mobx-state-tree': __moduleId('mobx-state-tree'),
'react-transition-group': __moduleId('react-transition-group'),
echarts: __moduleId('echarts'),
zrender: __moduleId('zrender'),
sortablejs: __moduleId('sortablejs'),
amis: __moduleId('../src'),
'amis/embed': __moduleId('./embed.tsx'),
'prop-types': __moduleId('prop-types'),
async: __moduleId('async'),
qs: __moduleId('qs')
};
function amisRequire(...args: Array<any>) {
let id = args.shift();
id = Array.isArray(id) ? id.map(id => mapping[id] || id) : mapping[id] || id;
args.unshift(id);
return require.apply(this, args);
};
let id = args.shift();
id = Array.isArray(id) ? id.map(id => mapping[id] || id) : mapping[id] || id;
args.unshift(id);
return require.apply(this, args);
}
(window as any).amisRequire = amisRequire;
(window as any).amisRequire = amisRequire;

View File

@ -1,46 +1,46 @@
// https://tc39.github.io/ecma262/#sec-array.prototype.find
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];
// 5. Let k be 0.
var k = 0;
// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return kValue.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];
// 5. Let k be 0.
var k = 0;
// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return kValue.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
// e. Increase k by 1.
k++;
}
// 7. Return undefined.
return undefined;
},
configurable: true,
writable: true
});
}
// e. Increase k by 1.
k++;
}
// 7. Return undefined.
return undefined;
},
configurable: true,
writable: true
});
}

View File

@ -1,77 +1,88 @@
if (!Array.from) {
Array.from = (function () {
var toStr = Object.prototype.toString;
var isCallable = function (fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function (value) {
var number = Number(value);
if (isNaN(number)) { return 0; }
if (number === 0 || !isFinite(number)) { return number; }
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function (value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike/*, mapFn, thisArg */) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError("Array.from requires an array-like object - not null or undefined");
Array.from = (function() {
var toStr = Object.prototype.toString;
var isCallable = function(fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function(value) {
var number = Number(value);
if (isNaN(number)) {
return 0;
}
if (number === 0 || !isFinite(number)) {
return number;
}
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function(value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike /*, mapFn, thisArg */) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError(
'Array.from requires an array-like object - not null or undefined'
);
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError(
'Array.from: when provided, the second argument must be a function'
);
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function');
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method
// of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len… (also steps a - h)
var kValue;
while (k < len) {
kValue = items[k];
if (mapFn) {
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else {
A[k] = kValue;
}
k += 1;
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method
// of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len… (also steps a - h)
var kValue;
while (k < len) {
kValue = items[k];
if (mapFn) {
A[k] =
typeof T === 'undefined'
? mapFn(kValue, k)
: mapFn.call(T, kValue, k);
} else {
A[k] = kValue;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
}());
}
k += 1;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
})();
}

View File

@ -1,29 +1,32 @@
if (typeof Object.assign != 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, "assign", {
value: function assign(target, varArgs) { // .length of function is 2
'use strict';
if (target == null) { // TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, 'assign', {
value: function assign(target, varArgs) {
// .length of function is 2
'use strict';
if (target == null) {
// TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource != null) {
// Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource != null) { // Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}

View File

@ -3,23 +3,24 @@
* @author mdn
*/
if (!Element.prototype.matches) {
Element.prototype.matches = Element.prototype.msMatchesSelector
|| Element.prototype.webkitMatchesSelector;
Element.prototype.matches =
Element.prototype.msMatchesSelector ||
Element.prototype.webkitMatchesSelector;
}
if (!Element.prototype.closest) {
Element.prototype.closest = function (s) {
var el = this;
if (!document.documentElement.contains(el)) {
return null;
}
Element.prototype.closest = function(s) {
var el = this;
if (!document.documentElement.contains(el)) {
return null;
}
do {
if (el.matches(s)) {
return el;
}
el = el.parentElement;
} while (el !== null);
return null;
};
do {
if (el.matches(s)) {
return el;
}
el = el.parentElement;
} while (el !== null);
return null;
};
}

View File

@ -4,4 +4,4 @@ import './Array.find';
import './cloest';
import 'promise/polyfill';
import 'es6-symbol/implement';
import 'es6-symbol/implement';

View File

@ -1,6 +1,6 @@
{
"name": "amis",
"version": "1.0.4",
"version": "1.0.4-beta.3",
"description": "一种MIS页面生成工具",
"main": "lib/index.js",
"scripts": {
@ -10,7 +10,7 @@
"stop": "fis3 server stop",
"dev": "fis3 release -cwd ./public",
"publish2npm": "sh publish.sh && npm publish",
"prettier": "prettier --write 'src/**/*.{tsx,ts}'"
"prettier": "prettier --write '{src,examples}/**/*.{tsx,ts,jsx}'"
},
"repository": {
"type": "git",

View File

@ -59,8 +59,6 @@
pointer-events: none;
position: fixed;
z-index: $zindex-toast;
width: 100%;
height: 100%;
}
width: $Toast-width;

View File

@ -13,202 +13,219 @@ import {RendererEnv, RendererProps} from './factory';
import {noop, autobind, qsstringify} from './utils/helper';
import {RendererData, Action} from './types';
interface ScopedComponentType extends React.Component<RendererProps> {
doAction?: (action: Action, data: RendererData, throwErrors?: boolean) => void;
receive?: (values: RendererData, subPath?: string) => void;
reload?: (subPath?: string, query?: RendererData | null, ctx?: RendererData) => void;
export interface ScopedComponentType extends React.Component<RendererProps> {
focus?: () => void;
doAction?: (
action: Action,
data: RendererData,
throwErrors?: boolean
) => void;
receive?: (values: RendererData, subPath?: string) => void;
reload?: (
subPath?: string,
query?: RendererData | null,
ctx?: RendererData
) => void;
}
export interface IScopedContext {
parent?: AlisIScopedContext;
registerComponent: (component: ScopedComponentType) => void;
unRegisterComponent: (component: ScopedComponentType) => void;
getComponentByName: (name: string) => ScopedComponentType | void;
getComponents: () => Array<ScopedComponentType>;
reload: (target: string, ctx: RendererData) => void;
send: (target: string, ctx: RendererData) => void;
parent?: AlisIScopedContext;
registerComponent: (component: ScopedComponentType) => void;
unRegisterComponent: (component: ScopedComponentType) => void;
getComponentByName: (name: string) => ScopedComponentType | void;
getComponents: () => Array<ScopedComponentType>;
reload: (target: string, ctx: RendererData) => void;
send: (target: string, ctx: RendererData) => void;
}
type AlisIScopedContext = IScopedContext;
export const ScopedContext = React.createContext(createScopedTools(''));
function createScopedTools(path?: string, parent?: AlisIScopedContext, env?: RendererEnv): IScopedContext {
const components: Array<ScopedComponentType> = [];
function createScopedTools(
path?: string,
parent?: AlisIScopedContext,
env?: RendererEnv
): IScopedContext {
const components: Array<ScopedComponentType> = [];
return {
parent,
registerComponent(component: ScopedComponentType) {
// 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给孩子们注册的。
if (component.props.$path === path && parent) {
return parent.registerComponent(component);
}
return {
parent,
registerComponent(component: ScopedComponentType) {
// 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给孩子们注册的。
if (component.props.$path === path && parent) {
return parent.registerComponent(component);
}
if (!~components.indexOf(component)) {
components.push(component);
}
},
if (!~components.indexOf(component)) {
components.push(component);
}
},
unRegisterComponent(component: ScopedComponentType) {
// 自己本身实际上注册在父级 Scoped 上。
if (component.props.$path === path && parent) {
return parent.unRegisterComponent(component);
}
unRegisterComponent(component: ScopedComponentType) {
// 自己本身实际上注册在父级 Scoped 上。
if (component.props.$path === path && parent) {
return parent.unRegisterComponent(component);
}
const idx = components.indexOf(component);
const idx = components.indexOf(component);
if (~idx) {
components.splice(idx, 1);
}
},
if (~idx) {
components.splice(idx, 1);
}
},
getComponentByName(name: string) {
if (~name.indexOf('.')) {
const paths = name.split('.');
const len = paths.length;
getComponentByName(name: string) {
if (~name.indexOf('.')) {
const paths = name.split('.');
const len = paths.length;
return paths.reduce((scope, name, idx) => {
if (scope && scope.getComponentByName) {
const result = scope.getComponentByName(name);
return result && idx < len - 1 ? result.context : result;
}
return paths.reduce((scope, name, idx) => {
if (scope && scope.getComponentByName) {
const result = scope.getComponentByName(name);
return result && idx < len - 1 ? result.context : result;
}
return null;
}, this);
}
return null;
}, this);
}
const resolved = find(
components,
component => component.props.name === name || component.props.id === name
);
return resolved || (parent && parent.getComponentByName(name));
},
const resolved = find(
components,
component =>
component.props.name === name || component.props.id === name
);
return resolved || (parent && parent.getComponentByName(name));
},
getComponents() {
return components.concat();
},
getComponents() {
return components.concat();
},
reload(target: string, ctx: any) {
const scoped = this;
reload(target: string, ctx: any) {
const scoped = this;
if (target === 'window') {
return location.reload();
}
if (target === 'window') {
return location.reload();
}
let targets = typeof target === 'string' ? target.split(/\s*,\s*/) : target;
targets.forEach(name => {
const idx2 = name.indexOf('?');
let query = null;
let targets =
typeof target === 'string' ? target.split(/\s*,\s*/) : target;
targets.forEach(name => {
const idx2 = name.indexOf('?');
let query = null;
if (~idx2) {
query = dataMapping(qs.parse(name.substring(idx2 + 1)), ctx);
name = name.substring(0, idx2);
}
const idx = name.indexOf('.');
let subPath = '';
if (~idx) {
subPath = name.substring(1 + idx);
name = name.substring(0, idx);
}
const component = scoped.getComponentByName(name);
component && component.reload && component.reload(subPath, query, ctx);
});
},
send(receive: string, values: object) {
const scoped = this;
let receives = typeof receive === 'string' ? receive.split(/\s*,\s*/) : receive;
// todo 没找到做提示!
receives.forEach(name => {
const idx = name.indexOf('.');
let subPath = '';
if (~idx) {
subPath = name.substring(1 + idx);
name = name.substring(0, idx);
}
const component = scoped.getComponentByName(name);
if (component && component.receive) {
component.receive(values, subPath);
} else if (name === 'window' && env && env.updateLocation) {
const query = {
...(location.search ? qs.parse(location.search.substring(1)) : {}),
...values
};
const link = location.pathname + '?' + qsstringify(query);
env.updateLocation(link);
}
});
if (~idx2) {
query = dataMapping(qs.parse(name.substring(idx2 + 1)), ctx);
name = name.substring(0, idx2);
}
};
const idx = name.indexOf('.');
let subPath = '';
if (~idx) {
subPath = name.substring(1 + idx);
name = name.substring(0, idx);
}
const component = scoped.getComponentByName(name);
component && component.reload && component.reload(subPath, query, ctx);
});
},
send(receive: string, values: object) {
const scoped = this;
let receives =
typeof receive === 'string' ? receive.split(/\s*,\s*/) : receive;
// todo 没找到做提示!
receives.forEach(name => {
const idx = name.indexOf('.');
let subPath = '';
if (~idx) {
subPath = name.substring(1 + idx);
name = name.substring(0, idx);
}
const component = scoped.getComponentByName(name);
if (component && component.receive) {
component.receive(values, subPath);
} else if (name === 'window' && env && env.updateLocation) {
const query = {
...(location.search ? qs.parse(location.search.substring(1)) : {}),
...values
};
const link = location.pathname + '?' + qsstringify(query);
env.updateLocation(link);
}
});
}
};
}
export function HocScoped<
T extends {
$path?: string;
env: RendererEnv;
}
T extends {
$path?: string;
env: RendererEnv;
}
>(
ComposedComponent: React.ComponentType<T>
ComposedComponent: React.ComponentType<T>
): React.ComponentType<
T & {
scopeRef?: (ref: any) => void;
}
T & {
scopeRef?: (ref: any) => void;
}
> & {
ComposedComponent: React.ComponentType<T>;
ComposedComponent: React.ComponentType<T>;
} {
class ScopedComponent extends React.Component<
T & {
scopeRef?: (ref: any) => void;
}
> {
static displayName = `Scoped(${ComposedComponent.displayName || ComposedComponent.name})`;
static contextType = ScopedContext;
static ComposedComponent = ComposedComponent;
ref: any;
class ScopedComponent extends React.Component<
T & {
scopeRef?: (ref: any) => void;
}
> {
static displayName = `Scoped(${ComposedComponent.displayName ||
ComposedComponent.name})`;
static contextType = ScopedContext;
static ComposedComponent = ComposedComponent;
ref: any;
getWrappedInstance() {
return this.ref;
}
@autobind
childRef(ref: any) {
while (ref && ref.getWrappedInstance) {
ref = ref.getWrappedInstance();
}
this.ref = ref;
}
scoped = createScopedTools(this.props.$path, this.context, this.props.env);
componentWillMount() {
const scopeRef = this.props.scopeRef;
scopeRef && scopeRef(this.scoped);
}
componentWillUnmount() {
const scopeRef = this.props.scopeRef;
scopeRef && scopeRef(null);
}
render() {
const {scopeRef, ...rest} = this.props;
return (
<ScopedContext.Provider value={this.scoped}>
<ComposedComponent {...rest as any /* todo */} ref={this.childRef} />
</ScopedContext.Provider>
);
}
getWrappedInstance() {
return this.ref;
}
hoistNonReactStatic(ScopedComponent, ComposedComponent);
return ScopedComponent;
@autobind
childRef(ref: any) {
while (ref && ref.getWrappedInstance) {
ref = ref.getWrappedInstance();
}
this.ref = ref;
}
scoped = createScopedTools(this.props.$path, this.context, this.props.env);
componentWillMount() {
const scopeRef = this.props.scopeRef;
scopeRef && scopeRef(this.scoped);
}
componentWillUnmount() {
const scopeRef = this.props.scopeRef;
scopeRef && scopeRef(null);
}
render() {
const {scopeRef, ...rest} = this.props;
return (
<ScopedContext.Provider value={this.scoped}>
<ComposedComponent {...rest as any /* todo */} ref={this.childRef} />
</ScopedContext.Provider>
);
}
}
hoistNonReactStatic(ScopedComponent, ComposedComponent);
return ScopedComponent;
}
export default HocScoped;

View File

@ -16,289 +16,304 @@ import {ServiceRenderer} from './renderers/Form/Service';
// 兼容老的用法,老用法 label 用在 checkbox 的右侧内容,新用法用 option 来代替。
addSchemaFilter(function CheckboxPropsFilter(schema: Schema, renderer) {
if (renderer.component !== CheckboxControlRenderer) {
return schema;
}
if (schema.label && typeof schema.option === 'undefined') {
schema = {
...schema
};
schema.option = schema.label;
delete schema.label;
}
if (renderer.component !== CheckboxControlRenderer) {
return schema;
}
if (schema.label && typeof schema.option === 'undefined') {
schema = {
...schema
};
schema.option = schema.label;
delete schema.label;
}
return schema;
});
function convertFieldSetTabs2Controls(schema: any) {
const toUpdate: any = {};
let flag = false;
const toUpdate: any = {};
let flag = false;
toUpdate.controls = Array.isArray(schema.controls) ? schema.controls.concat() : [];
toUpdate.controls = toUpdate.controls.map((control: any) => {
if (Array.isArray(control)) {
let converted = convertFieldSetTabs2Controls({
type: 'group',
controls: control
});
toUpdate.controls = Array.isArray(schema.controls)
? schema.controls.concat()
: [];
toUpdate.controls = toUpdate.controls.map((control: any) => {
if (Array.isArray(control)) {
let converted = convertFieldSetTabs2Controls({
type: 'group',
controls: control
});
if (converted !== control) {
flag = true;
}
if (converted !== control) {
flag = true;
}
return converted;
}
return control;
return converted;
}
return control;
});
schema.fieldSet &&
(Array.isArray(schema.fieldSet)
? schema.fieldSet
: [schema.fieldSet]
).forEach((fieldSet: any) => {
flag = true;
toUpdate.controls.push({
...convertFieldSetTabs2Controls(fieldSet),
type: 'fieldSet',
collapsable: schema.collapsable
});
});
schema.fieldSet &&
(Array.isArray(schema.fieldSet) ? schema.fieldSet : [schema.fieldSet]).forEach((fieldSet: any) => {
flag = true;
toUpdate.controls.push({
...convertFieldSetTabs2Controls(fieldSet),
type: 'fieldSet',
collapsable: schema.collapsable
});
});
schema.tabs &&
(flag = true) &&
toUpdate.controls.push({
type: 'tabs',
tabs: schema.tabs.map((tab: any) => convertFieldSetTabs2Controls(tab))
});
schema.tabs &&
(flag = true) &&
toUpdate.controls.push({
type: 'tabs',
tabs: schema.tabs.map((tab: any) => convertFieldSetTabs2Controls(tab))
});
if (flag) {
schema = {
...schema,
...toUpdate
};
delete schema.fieldSet;
delete schema.tabs;
}
return schema;
if (flag) {
schema = {
...schema,
...toUpdate
};
delete schema.fieldSet;
delete schema.tabs;
}
return schema;
}
// Form 中,把 fieldSet 和 tabs 转成 {type: 'fieldSet', controls: []}
// 同时把数组用法转成 {type: 'group', controls: []}
addSchemaFilter(function FormPropsFilter(schema: Schema, renderer) {
if (renderer.component !== FormRenderer) {
return schema;
}
if (renderer.component !== FormRenderer) {
return schema;
}
if (schema.fieldSet || schema.tabs) {
// console.warn('Form 下面直接用 fieldSet 或者 tabs 将不支持,请改成在 controls 数组中添加。');
schema = convertFieldSetTabs2Controls(schema);
} else if (Array.isArray(schema.controls)) {
let flag = false;
let converted = schema.controls.map((control: any) => {
if (Array.isArray(control)) {
let converted = convertFieldSetTabs2Controls({
type: 'group',
controls: control
});
if (converted !== control) {
flag = true;
}
return converted;
}
return control;
if (schema.fieldSet || schema.tabs) {
// console.warn('Form 下面直接用 fieldSet 或者 tabs 将不支持,请改成在 controls 数组中添加。');
schema = convertFieldSetTabs2Controls(schema);
} else if (Array.isArray(schema.controls)) {
let flag = false;
let converted = schema.controls.map((control: any) => {
if (Array.isArray(control)) {
let converted = convertFieldSetTabs2Controls({
type: 'group',
controls: control
});
if (flag) {
schema = {
...schema,
controls: converted
};
if (converted !== control) {
flag = true;
}
}
return converted;
}
return control;
});
return schema;
if (flag) {
schema = {
...schema,
controls: converted
};
}
}
return schema;
});
// FieldSet 中把 controls 里面的数组用法转成 {type: 'group', controls: []}
addSchemaFilter(function FormPropsFilter(schema: Schema, renderer) {
if (renderer.component !== FieldSetRenderer) {
return schema;
}
if (renderer.component !== FieldSetRenderer) {
return schema;
}
if (Array.isArray(schema.controls)) {
let flag = false;
let converted = schema.controls.map((control: any) => {
if (Array.isArray(control)) {
let converted = convertFieldSetTabs2Controls({
type: 'group',
controls: control
});
if (converted !== control) {
flag = true;
}
return converted;
}
return control;
if (Array.isArray(schema.controls)) {
let flag = false;
let converted = schema.controls.map((control: any) => {
if (Array.isArray(control)) {
let converted = convertFieldSetTabs2Controls({
type: 'group',
controls: control
});
if (flag) {
schema = {
...schema,
controls: converted
};
if (converted !== control) {
flag = true;
}
}
return converted;
}
return control;
});
return schema;
if (flag) {
schema = {
...schema,
controls: converted
};
}
}
return schema;
});
// Form 里面的 Tabs 中把 controls 里面的数组用法转成 {type: 'group', controls: []}
addSchemaFilter(function FormPropsFilter(schema: Schema, renderer) {
if (renderer.component !== TabsRenderer) {
return schema;
}
if (Array.isArray(schema.tabs)) {
let flag = false;
let converted = schema.tabs.map((tab: any) => {
let flag2 = false;
let converted = (tab.controls || []).map((control: any) => {
if (Array.isArray(control)) {
let converted = convertFieldSetTabs2Controls({
type: 'group',
controls: control
});
if (converted !== control) {
flag2 = true;
}
return converted;
}
return control;
});
if (flag2) {
flag = true;
tab = {
...tab,
controls: converted
};
}
return tab;
});
if (flag) {
schema = {
...schema,
tabs: converted
};
}
}
if (renderer.component !== TabsRenderer) {
return schema;
}
if (Array.isArray(schema.tabs)) {
let flag = false;
let converted = schema.tabs.map((tab: any) => {
let flag2 = false;
let converted = (tab.controls || []).map((control: any) => {
if (Array.isArray(control)) {
let converted = convertFieldSetTabs2Controls({
type: 'group',
controls: control
});
if (converted !== control) {
flag2 = true;
}
return converted;
}
return control;
});
if (flag2) {
flag = true;
tab = {
...tab,
controls: converted
};
}
return tab;
});
if (flag) {
schema = {
...schema,
tabs: converted
};
}
}
return schema;
});
function convertArray2Hbox(arr: Array<any>): any {
let flag = false;
let converted = arr.map((item: any) => {
if (Array.isArray(item)) {
flag = true;
return convertArray2Hbox(item);
}
return item;
});
if (!flag) {
converted = arr;
let flag = false;
let converted = arr.map((item: any) => {
if (Array.isArray(item)) {
flag = true;
return convertArray2Hbox(item);
}
return {
type: 'hbox',
columns: converted
};
return item;
});
if (!flag) {
converted = arr;
}
return {
type: 'hbox',
columns: converted
};
}
// CRUD/List 和 CRUD/Card 的 body 中的数组用法转成 hbox
addSchemaFilter(function(schema: Schema, renderer) {
if (renderer.component !== CardRenderer && renderer.component !== ListItemRenderer) {
return schema;
}
if (Array.isArray(schema.body)) {
let flag = false;
let converted = schema.body.map((item: any) => {
if (Array.isArray(item)) {
flag = true;
return convertArray2Hbox(item);
}
return item;
});
if (flag) {
schema = {
...schema,
body: converted
};
}
}
if (
renderer.component !== CardRenderer &&
renderer.component !== ListItemRenderer
) {
return schema;
}
if (Array.isArray(schema.body)) {
let flag = false;
let converted = schema.body.map((item: any) => {
if (Array.isArray(item)) {
flag = true;
return convertArray2Hbox(item);
}
return item;
});
if (flag) {
schema = {
...schema,
body: converted
};
}
}
return schema;
});
// button group 的 btnClassName 和 btnActiveClassName 改成 btnLevel 和 btnActiveLevel 了
addSchemaFilter(function(scheam: Schema, renderer) {
if (renderer.component !== ButtonGroupControlRenderer) {
return scheam;
}
if (scheam.btnClassName || scheam.btnActiveClassName) {
scheam = {
...scheam,
btnLevel: getLevelFromClassName(scheam.btnClassName),
btnActiveLevel: getLevelFromClassName(scheam.btnActiveClassName)
};
delete scheam.btnClassName;
delete scheam.btnActiveClassName;
}
if (renderer.component !== ButtonGroupControlRenderer) {
return scheam;
}
if (scheam.btnClassName || scheam.btnActiveClassName) {
scheam = {
...scheam,
btnLevel: getLevelFromClassName(scheam.btnClassName),
btnActiveLevel: getLevelFromClassName(scheam.btnActiveClassName)
};
delete scheam.btnClassName;
delete scheam.btnActiveClassName;
}
return scheam;
});
// FieldSet className 定制样式方式改成 size 来配置
addSchemaFilter(function(scheam: Schema, renderer) {
if (renderer.component !== FieldSetRenderer) {
return scheam;
}
if (scheam.className && !scheam.size && /\bfieldset(?:\-(xs|sm|md|lg))?\b/.test(scheam.className)) {
scheam = {
...scheam,
size: RegExp.$1 || 'base',
className: scheam.className.replace(/\bfieldset(?:\-(xs|sm|md|lg))?\b/, '')
};
delete scheam.btnClassName;
delete scheam.btnActiveClassName;
}
if (renderer.component !== FieldSetRenderer) {
return scheam;
}
if (
scheam.className &&
!scheam.size &&
/\bfieldset(?:\-(xs|sm|md|lg))?\b/.test(scheam.className)
) {
scheam = {
...scheam,
size: RegExp.$1 || 'base',
className: scheam.className.replace(
/\bfieldset(?:\-(xs|sm|md|lg))?\b/,
''
)
};
delete scheam.btnClassName;
delete scheam.btnActiveClassName;
}
return scheam;
});
// FieldSet className 定制样式方式改成 size 来配置
addSchemaFilter(function(scheam: Schema, renderer) {
if (renderer.component !== ServiceRenderer) {
return scheam;
}
if (scheam.body && scheam.body.controls) {
scheam = {
...scheam,
controls: scheam.body.controls
};
delete scheam.body;
}
if (renderer.component !== ServiceRenderer) {
return scheam;
}
if (scheam.body && scheam.body.controls) {
scheam = {
...scheam,
controls: scheam.body.controls
};
delete scheam.body;
}
return scheam;
});

View File

@ -7,39 +7,43 @@ import React from 'react';
import {themeable, ClassNamesFn} from '../theme';
interface NotFoundProps {
code?: string | number;
description?: string;
links?: React.ReactNode;
footerText?: React.ReactNode;
classPrefix: string;
classnames: ClassNamesFn;
code?: string | number;
description?: string;
links?: React.ReactNode;
footerText?: React.ReactNode;
classPrefix: string;
classnames: ClassNamesFn;
}
export class NotFound extends React.Component<NotFoundProps, any> {
render() {
const {links, footerText, description, children, code} = this.props;
render() {
const {links, footerText, description, children, code} = this.props;
return (
<div className="container w-xxl w-auto-xs">
<div className="text-center m-b-lg">
<h1 className="text-shadow text-white">{code || '404'}</h1>
{description ? <div className="text-danger">{description}</div> : null}
</div>
return (
<div className="container w-xxl w-auto-xs">
<div className="text-center m-b-lg">
<h1 className="text-shadow text-white">{code || '404'}</h1>
{description ? (
<div className="text-danger">{description}</div>
) : null}
</div>
{children}
{children}
{links ? <div className="list-group bg-info auto m-b-sm m-b-lg">{links}</div> : null}
{links ? (
<div className="list-group bg-info auto m-b-sm m-b-lg">{links}</div>
) : null}
{footerText ? (
<div className="text-center">
<p>
<small className="text-muted">{footerText}</small>
</p>
</div>
) : null}
</div>
);
}
{footerText ? (
<div className="text-center">
<p>
<small className="text-muted">{footerText}</small>
</p>
</div>
) : null}
</div>
);
}
}
export default themeable(NotFound);

View File

@ -10,166 +10,180 @@ import Button from './Button';
import {ClassNamesFn, themeable} from '../theme';
export interface AlertProps {
container?: any;
confirmText?: string;
cancelText?: string;
title?: string;
confirmBtnLevel?: string;
alertBtnLevel?: string;
classPrefix: string;
classnames: ClassNamesFn;
theme?: string;
container?: any;
confirmText?: string;
cancelText?: string;
title?: string;
confirmBtnLevel?: string;
alertBtnLevel?: string;
classPrefix: string;
classnames: ClassNamesFn;
theme?: string;
}
export interface AlertState {
show: boolean;
title?: string;
content: string;
confirm: boolean;
show: boolean;
title?: string;
content: string;
confirm: boolean;
}
export class Alert extends React.Component<AlertProps, AlertState> {
static instance: any = null;
static getInstance() {
if (!Alert.instance) {
console.warn('Alert 组件应该没有被渲染,所以隐性的渲染到 body 了');
const container = document.body;
const div = document.createElement('div');
container.appendChild(div);
render(<ThemedAlert />, div);
}
return Alert.instance;
static instance: any = null;
static getInstance() {
if (!Alert.instance) {
console.warn('Alert 组件应该没有被渲染,所以隐性的渲染到 body 了');
const container = document.body;
const div = document.createElement('div');
container.appendChild(div);
render(<ThemedAlert />, div);
}
_resolve: (value: any) => void;
_modal: any;
_body: any;
state: AlertState = {
show: false,
title: '',
content: '',
confirm: false
};
constructor(props: AlertProps) {
super(props);
return Alert.instance;
}
this.close = this.close.bind(this);
this.handleConfirm = this.handleConfirm.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.modalRef = this.modalRef.bind(this);
this.bodyRef = this.bodyRef.bind(this);
_resolve: (value: any) => void;
_modal: any;
_body: any;
state: AlertState = {
show: false,
title: '',
content: '',
confirm: false
};
constructor(props: AlertProps) {
super(props);
this.close = this.close.bind(this);
this.handleConfirm = this.handleConfirm.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.modalRef = this.modalRef.bind(this);
this.bodyRef = this.bodyRef.bind(this);
}
static defaultProps = {
confirmText: '确认',
cancelText: '取消',
title: '系统消息',
alertBtnLevel: 'primary',
confirmBtnLevel: 'danger'
};
componentWillMount() {
Alert.instance = this;
}
componentDidMount() {
this._body && (this._body.innerHTML = this.state.content);
}
componentDidUpdate(prevProps: AlertProps, prevState: AlertState) {
if (prevState.content !== this.state.content) {
this._body && (this._body.innerHTML = this.state.content);
}
}
static defaultProps = {
confirmText: '确认',
cancelText: '取消',
title: '系统消息',
alertBtnLevel: 'primary',
confirmBtnLevel: 'danger'
};
componentWillUnmount() {
Alert.instance = null;
}
componentWillMount() {
Alert.instance = this;
}
handleConfirm() {
this.close(true);
}
componentDidMount() {
this._body && (this._body.innerHTML = this.state.content);
}
handleCancel() {
this.close(false);
}
componentDidUpdate(prevProps: AlertProps, prevState: AlertState) {
if (prevState.content !== this.state.content) {
this._body && (this._body.innerHTML = this.state.content);
}
}
close(confirmed: boolean) {
const isConfirm = this.state.confirm;
componentWillUnmount() {
Alert.instance = null;
}
this.setState(
{
show: false
},
isConfirm ? () => this._resolve(confirmed) /*this._reject()*/ : undefined
);
}
handleConfirm() {
this.close(true);
}
alert(content: string, title?: string) {
this.setState({
title,
content,
show: true,
confirm: false
});
}
handleCancel() {
this.close(false);
}
confirm(content: string, title?: string) {
this.setState({
title,
content,
show: true,
confirm: true
});
close(confirmed: boolean) {
const isConfirm = this.state.confirm;
return new Promise(resolve => {
this._resolve = resolve;
});
}
this.setState(
{
show: false
},
isConfirm ? () => this._resolve(confirmed) /*this._reject()*/ : undefined
);
}
modalRef(ref: any) {
this._modal = ref;
}
alert(content: string, title?: string) {
this.setState({
title,
content,
show: true,
confirm: false
});
}
bodyRef(ref: any) {
this._body = ref;
this._body && (this._body.innerHTML = this.state.content);
}
confirm(content: string, title?: string) {
this.setState({
title,
content,
show: true,
confirm: true
});
return new Promise(resolve => {
this._resolve = resolve;
});
}
modalRef(ref: any) {
this._modal = ref;
}
bodyRef(ref: any) {
this._body = ref;
this._body && (this._body.innerHTML = this.state.content);
}
render() {
const {
container,
cancelText,
confirmText,
title,
confirmBtnLevel,
alertBtnLevel,
classnames: cx,
classPrefix
} = this.props;
return (
<Modal show={this.state.show} onHide={this.handleCancel} container={container} ref={this.modalRef}>
<div className={cx('Modal-header')}>
<div className={cx('Modal-title')}>{this.state.title || title}</div>
</div>
<div className={cx('Modal-body')}>
<div ref={this.bodyRef} />
</div>
<div className={cx('Modal-footer')}>
{this.state.confirm ? <Button onClick={this.handleCancel}>{cancelText}</Button> : null}
<Button level={this.state.confirm ? confirmBtnLevel : alertBtnLevel} onClick={this.handleConfirm}>
{confirmText}
</Button>
</div>
</Modal>
);
}
render() {
const {
container,
cancelText,
confirmText,
title,
confirmBtnLevel,
alertBtnLevel,
classnames: cx,
classPrefix
} = this.props;
return (
<Modal
show={this.state.show}
onHide={this.handleCancel}
container={container}
ref={this.modalRef}
>
<div className={cx('Modal-header')}>
<div className={cx('Modal-title')}>{this.state.title || title}</div>
</div>
<div className={cx('Modal-body')}>
<div ref={this.bodyRef} />
</div>
<div className={cx('Modal-footer')}>
{this.state.confirm ? (
<Button onClick={this.handleCancel}>{cancelText}</Button>
) : null}
<Button
level={this.state.confirm ? confirmBtnLevel : alertBtnLevel}
onClick={this.handleConfirm}
>
{confirmText}
</Button>
</div>
</Modal>
);
}
}
export const alert: (content: string, title?: string) => void = (content, title) =>
Alert.getInstance().alert(content, title);
export const confirm: (content: string, title?: string) => Promise<any> = (content, title) =>
Alert.getInstance().confirm(content, title);
export const alert: (content: string, title?: string) => void = (
content,
title
) => Alert.getInstance().alert(content, title);
export const confirm: (content: string, title?: string) => Promise<any> = (
content,
title
) => Alert.getInstance().confirm(content, title);
export const ThemedAlert = themeable(Alert);
export default ThemedAlert;

View File

@ -7,58 +7,76 @@ import React from 'react';
import {ClassNamesFn, themeable} from '../theme';
export interface AlertProps {
level: 'danger' | 'info' | 'success' | 'warning';
className: string;
showCloseButton: boolean;
onClose?: () => void;
classnames: ClassNamesFn;
classPrefix: string;
level: 'danger' | 'info' | 'success' | 'warning';
className: string;
showCloseButton: boolean;
onClose?: () => void;
classnames: ClassNamesFn;
classPrefix: string;
}
export interface AlertState {
show: boolean;
show: boolean;
}
export class Alert extends React.Component<AlertProps, AlertState> {
static defaultProps: Pick<AlertProps, 'level' | 'className' | 'showCloseButton'> = {
level: 'info',
className: '',
showCloseButton: false
static defaultProps: Pick<
AlertProps,
'level' | 'className' | 'showCloseButton'
> = {
level: 'info',
className: '',
showCloseButton: false
};
static propsList: Array<string> = [
'level',
'className',
'showCloseButton',
'onClose'
];
constructor(props: AlertProps) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
show: true
};
static propsList: Array<string> = ['level', 'className', 'showCloseButton', 'onClose'];
}
constructor(props: AlertProps) {
super(props);
handleClick() {
this.setState(
{
show: false
},
this.props.onClose
);
}
this.handleClick = this.handleClick.bind(this);
this.state = {
show: true
};
}
render() {
const {
classnames: cx,
className,
level,
children,
showCloseButton
} = this.props;
handleClick() {
this.setState(
{
show: false
},
this.props.onClose
);
}
render() {
const {classnames: cx, className, level, children, showCloseButton} = this.props;
return this.state.show ? (
<div className={cx('Alert', level ? `Alert--${level}` : '', className)}>
{showCloseButton ? (
<button className={cx('Alert-close')} onClick={this.handleClick} type="button">
<span>×</span>
</button>
) : null}
{children}
</div>
) : null;
}
return this.state.show ? (
<div className={cx('Alert', level ? `Alert--${level}` : '', className)}>
{showCloseButton ? (
<button
className={cx('Alert-close')}
onClick={this.handleClick}
type="button"
>
<span>×</span>
</button>
) : null}
{children}
</div>
) : null;
}
}
export default themeable(Alert);

View File

@ -11,218 +11,254 @@ import {ClassNamesFn, themeable} from '../theme';
export type LinkItem = LinkItemProps;
interface LinkItemProps {
id?: number;
label: string;
hidden?: boolean;
open?: boolean;
active?: boolean;
className?: string;
children?: Array<LinkItem>;
path?: string;
icon?: string;
component?: React.ReactType;
id?: number;
label: string;
hidden?: boolean;
open?: boolean;
active?: boolean;
className?: string;
children?: Array<LinkItem>;
path?: string;
icon?: string;
component?: React.ReactType;
}
interface Navigation {
label: string;
children: Array<LinkItem>;
prefix?: JSX.Element;
affix?: JSX.Element;
className?: string;
[propName: string]: any;
label: string;
children: Array<LinkItem>;
prefix?: JSX.Element;
affix?: JSX.Element;
className?: string;
[propName: string]: any;
}
interface AsideNavProps {
id?: string;
className?: string;
classPrefix: string;
classnames: ClassNamesFn;
renderLink: Function;
isActive: Function;
isOpen: (link: LinkItemProps) => boolean;
navigations: Array<Navigation>;
renderSubLinks: (link: LinkItemProps, renderLink: Function, depth: number, props: AsideNavProps) => React.ReactNode;
id?: string;
className?: string;
classPrefix: string;
classnames: ClassNamesFn;
renderLink: Function;
isActive: Function;
isOpen: (link: LinkItemProps) => boolean;
navigations: Array<Navigation>;
renderSubLinks: (
link: LinkItemProps,
renderLink: Function,
depth: number,
props: AsideNavProps
) => React.ReactNode;
}
interface AsideNavState {
navigations: Array<Navigation>;
navigations: Array<Navigation>;
}
export class AsideNav extends React.Component<AsideNavProps, AsideNavState> {
static defaultProps = {
renderLink: (item: LinkItemProps) => <a>{item.label}</a>,
renderSubLinks: (link: LinkItemProps, renderLink: Function, depth: number, {classnames: cx}: AsideNavProps) =>
link.children && link.children.length ? (
<ul className={cx('AsideNav-subList')}>
{link.label ? (
<li key="subHeader" className={cx('AsideNav-subHeader')}>
<a>{link.label}</a>
</li>
) : null}
{link.children.map((link, key) => renderLink(link, key, {}, depth + 1))}
</ul>
) : link.label && depth === 1 ? (
<div className={cx('AsideNav-tooltip')}>{link.label}</div>
) : null,
isActive: (link: LinkItem) => link.open,
isOpen: (item: LinkItemProps) => (item.children ? item.children.some(item => item.open) : false)
static defaultProps = {
renderLink: (item: LinkItemProps) => <a>{item.label}</a>,
renderSubLinks: (
link: LinkItemProps,
renderLink: Function,
depth: number,
{classnames: cx}: AsideNavProps
) =>
link.children && link.children.length ? (
<ul className={cx('AsideNav-subList')}>
{link.label ? (
<li key="subHeader" className={cx('AsideNav-subHeader')}>
<a>{link.label}</a>
</li>
) : null}
{link.children.map((link, key) =>
renderLink(link, key, {}, depth + 1)
)}
</ul>
) : link.label && depth === 1 ? (
<div className={cx('AsideNav-tooltip')}>{link.label}</div>
) : null,
isActive: (link: LinkItem) => link.open,
isOpen: (item: LinkItemProps) =>
item.children ? item.children.some(item => item.open) : false
};
constructor(props: AsideNavProps) {
super(props);
const isOpen = props.isOpen;
let id = 1;
this.state = {
navigations: mapTree(
props.navigations,
(item: Navigation) => {
const isActive =
typeof item.active === 'undefined'
? (props.isActive as Function)(item)
: item.active;
return {
...item,
id: id++,
active: isActive,
open: isActive || isOpen(item as LinkItemProps)
};
},
1,
true
)
};
constructor(props: AsideNavProps) {
super(props);
this.renderLink = this.renderLink.bind(this);
this.toggleExpand = this.toggleExpand.bind(this);
}
const isOpen = props.isOpen;
let id = 1;
this.state = {
navigations: mapTree(
props.navigations,
(item: Navigation) => {
const isActive =
typeof item.active === 'undefined' ? (props.isActive as Function)(item) : item.active;
componentWillReceiveProps(nextProps: AsideNavProps) {
const props = this.props;
const isOpen = props.isOpen;
return {
...item,
id: id++,
active: isActive,
open: isActive || isOpen(item as LinkItemProps)
};
},
1,
true
)
};
if (
props.navigations !== nextProps.navigations ||
props.isActive !== nextProps.isActive
) {
let id = 1;
this.setState({
navigations: mapTree(
nextProps.navigations,
(item: Navigation) => {
const isActive =
typeof item.active === 'undefined'
? (nextProps.isActive as Function)(item)
: item.active;
this.renderLink = this.renderLink.bind(this);
this.toggleExpand = this.toggleExpand.bind(this);
return {
...item,
id: id++,
active: isActive,
open: isActive || isOpen(item as LinkItemProps)
};
},
1,
true
)
});
}
}
toggleExpand(link: LinkItemProps, e?: React.MouseEvent<HTMLElement>) {
if (e) {
e.stopPropagation();
e.preventDefault();
}
componentWillReceiveProps(nextProps: AsideNavProps) {
const props = this.props;
const isOpen = props.isOpen;
this.setState({
navigations: mapTree(
this.state.navigations,
(item: Navigation) => ({
...item,
open: link.id === item.id ? !item.open : item.open
}),
1,
true
)
});
}
if (props.navigations !== nextProps.navigations || props.isActive !== nextProps.isActive) {
let id = 1;
this.setState({
navigations: mapTree(
nextProps.navigations,
(item: Navigation) => {
const isActive =
typeof item.active === 'undefined' ? (nextProps.isActive as Function)(item) : item.active;
renderLink(
link: LinkItemProps,
key: any,
props: Partial<AsideNavProps> = {},
depth = 1
): React.ReactNode {
const {
renderLink,
isActive,
renderSubLinks,
classnames: cx,
...others
} = this.props;
return {
...item,
id: id++,
active: isActive,
open: isActive || isOpen(item as LinkItemProps)
};
},
1,
true
)
});
}
const dom = (renderLink as Function)({
link,
active: link.active,
open: link.open,
toggleExpand: this.toggleExpand,
depth,
classnames: cx,
...others
});
if (!dom) {
return;
}
toggleExpand(link: LinkItemProps, e?: React.MouseEvent<HTMLElement>) {
if (e) {
e.stopPropagation();
e.preventDefault();
}
return (
<li
{...props}
key={key}
className={cx(`AsideNav-item`, link.className, {
[`is-open`]: link.open,
[`is-active`]: link.active
})}
>
{dom}
{renderSubLinks(link, this.renderLink, depth, this.props)}
</li>
);
}
this.setState({
navigations: mapTree(
this.state.navigations,
(item: Navigation) => ({
...item,
open: link.id === item.id ? !item.open : item.open
}),
1,
true
)
});
}
render() {
const navigations = this.state.navigations;
let links: Array<React.ReactNode> = [];
const {className, classnames: cx} = this.props;
renderLink(link: LinkItemProps, key: any, props: Partial<AsideNavProps> = {}, depth = 1): React.ReactNode {
const {renderLink, isActive, renderSubLinks, classnames: cx, ...others} = this.props;
const dom = (renderLink as Function)({
link,
active: link.active,
open: link.open,
toggleExpand: this.toggleExpand,
depth,
classnames: cx,
...others
});
if (!dom) {
return;
}
return (
<li
{...props}
key={key}
className={cx(`AsideNav-item`, link.className, {
[`is-open`]: link.open,
[`is-active`]: link.active
})}
>
{dom}
{renderSubLinks(link, this.renderLink, depth, this.props)}
</li>
navigations.forEach((navigation, index) => {
if (navigation.prefix) {
const prefix: JSX.Element =
typeof navigation.prefix === 'function'
? (navigation.prefix as any)(this.props)
: navigation.prefix;
links.push(
React.cloneElement(prefix, {
...prefix.props,
key: `${index}-prefix`
})
);
}
}
render() {
const navigations = this.state.navigations;
let links: Array<React.ReactNode> = [];
const {className, classnames: cx} = this.props;
navigations.forEach((navigation, index) => {
if (navigation.prefix) {
const prefix: JSX.Element =
typeof navigation.prefix === 'function'
? (navigation.prefix as any)(this.props)
: navigation.prefix;
links.push(
React.cloneElement(prefix, {
...prefix.props,
key: `${index}-prefix`
})
);
}
navigation.label &&
links.push(
<li key={`${index}-label`} className={cx(`AsideNav-label`, navigation.className)}>
<span>{navigation.label}</span>
</li>
);
navigation.children.forEach((item, key) => {
const link = this.renderLink(item, `${index}-${key}`);
link && links.push(link);
});
if (navigation.affix) {
const affix: JSX.Element =
typeof navigation.affix === 'function' ? (navigation.affix as any)(this.props) : navigation.affix;
links.push(
React.cloneElement(affix, {
...affix.props,
key: `${index}-affix`
})
);
}
});
return (
<nav className={cx(`AsideNav`, className)}>
<ul className={cx(`AsideNav-list`)}>{links}</ul>
</nav>
navigation.label &&
links.push(
<li
key={`${index}-label`}
className={cx(`AsideNav-label`, navigation.className)}
>
<span>{navigation.label}</span>
</li>
);
}
navigation.children.forEach((item, key) => {
const link = this.renderLink(item, `${index}-${key}`);
link && links.push(link);
});
if (navigation.affix) {
const affix: JSX.Element =
typeof navigation.affix === 'function'
? (navigation.affix as any)(this.props)
: navigation.affix;
links.push(
React.cloneElement(affix, {
...affix.props,
key: `${index}-affix`
})
);
}
});
return (
<nav className={cx(`AsideNav`, className)}>
<ul className={cx(`AsideNav-list`)}>{links}</ul>
</nav>
);
}
}
export default themeable(AsideNav);

View File

@ -9,116 +9,126 @@ import {pickEventsProps} from '../utils/helper';
import {ClassNamesFn, themeable} from '../theme';
interface ButtonProps
extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
id?: string;
className?: string;
href?: string;
size?: 'xs' | 'sm' | 'md' | 'lg';
type: 'button' | 'reset' | 'submit';
level: string; // 'link' | 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'danger' | 'light' | 'dark' | 'default';
tooltip?: string | TooltipObject;
placement: 'top' | 'right' | 'bottom' | 'left';
tooltipContainer?: any;
tooltipTrigger: Trigger | Array<Trigger>;
tooltipRootClose: boolean;
disabled?: boolean;
active?: boolean;
block?: boolean;
iconOnly?: boolean;
disabledTip?: string | TooltipObject;
classPrefix: string;
classnames: ClassNamesFn;
componentClass: React.ReactType;
extends React.DetailedHTMLProps<
React.ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
> {
id?: string;
className?: string;
href?: string;
size?: 'xs' | 'sm' | 'md' | 'lg';
type: 'button' | 'reset' | 'submit';
level: string; // 'link' | 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'danger' | 'light' | 'dark' | 'default';
tooltip?: string | TooltipObject;
placement: 'top' | 'right' | 'bottom' | 'left';
tooltipContainer?: any;
tooltipTrigger: Trigger | Array<Trigger>;
tooltipRootClose: boolean;
disabled?: boolean;
active?: boolean;
block?: boolean;
iconOnly?: boolean;
disabledTip?: string | TooltipObject;
classPrefix: string;
classnames: ClassNamesFn;
componentClass: React.ReactType;
}
export class Button extends React.Component<ButtonProps> {
static defaultProps: Pick<
ButtonProps,
'componentClass' | 'level' | 'type' | 'placement' | 'tooltipTrigger' | 'tooltipRootClose'
> = {
componentClass: 'button',
level: 'default',
type: 'button',
placement: 'top',
tooltipTrigger: ['hover', 'focus'],
tooltipRootClose: false
};
static defaultProps: Pick<
ButtonProps,
| 'componentClass'
| 'level'
| 'type'
| 'placement'
| 'tooltipTrigger'
| 'tooltipRootClose'
> = {
componentClass: 'button',
level: 'default',
type: 'button',
placement: 'top',
tooltipTrigger: ['hover', 'focus'],
tooltipRootClose: false
};
renderButton() {
let {
level,
size,
disabled,
className,
componentClass: Comp,
classnames: cx,
children,
disabledTip,
block,
type,
active,
iconOnly,
href,
...rest
} = this.props;
renderButton() {
let {
level,
size,
disabled,
className,
componentClass: Comp,
classnames: cx,
children,
disabledTip,
block,
type,
active,
iconOnly,
href,
...rest
} = this.props;
if (href) {
Comp = 'a';
}
return (
<Comp
type={Comp === 'a' ? undefined : type}
{...pickEventsProps(rest)}
href={href}
className={cx(
`Button`,
{
[`Button--${level}`]: level,
[`Button--${size}`]: size,
[`Button--block`]: block,
[`Button--iconOnly`]: iconOnly,
'is-disabled': disabled,
'is-active': active
},
className
)}
disabled={disabled}
>
{children}
</Comp>
);
if (href) {
Comp = 'a';
}
render() {
const {
tooltip,
placement,
tooltipContainer,
tooltipTrigger,
tooltipRootClose,
disabled,
disabledTip,
classPrefix,
classnames: cx
} = this.props;
return (
<Comp
type={Comp === 'a' ? undefined : type}
{...pickEventsProps(rest)}
href={href}
className={cx(
`Button`,
{
[`Button--${level}`]: level,
[`Button--${size}`]: size,
[`Button--block`]: block,
[`Button--iconOnly`]: iconOnly,
'is-disabled': disabled,
'is-active': active
},
className
)}
disabled={disabled}
>
{children}
</Comp>
);
}
return (
<TooltipWrapper
placement={placement}
tooltip={disabled ? disabledTip : tooltip}
container={tooltipContainer}
trigger={tooltipTrigger}
rootClose={tooltipRootClose}
>
{disabled && disabledTip ? (
<div className={cx('Button--disabled-wrap')}>{this.renderButton()}</div>
) : (
this.renderButton()
)}
</TooltipWrapper>
);
}
render() {
const {
tooltip,
placement,
tooltipContainer,
tooltipTrigger,
tooltipRootClose,
disabled,
disabledTip,
classPrefix,
classnames: cx
} = this.props;
return (
<TooltipWrapper
placement={placement}
tooltip={disabled ? disabledTip : tooltip}
container={tooltipContainer}
trigger={tooltipTrigger}
rootClose={tooltipRootClose}
>
{disabled && disabledTip ? (
<div className={cx('Button--disabled-wrap')}>
{this.renderButton()}
</div>
) : (
this.renderButton()
)}
</TooltipWrapper>
);
}
}
export default themeable(Button);

View File

@ -7,111 +7,115 @@ import React from 'react';
import cx from 'classnames';
import {ClassNamesFn, themeable} from '../theme';
import {autobind} from '../utils/helper';
import { filter } from '../utils/tpl';
import {filter} from '../utils/tpl';
const sizeMap = {
sm: 'i-checks-sm',
lg: 'i-checks-lg',
small: 'i-checks-sm',
large: 'i-checks-lg'
sm: 'i-checks-sm',
lg: 'i-checks-lg',
small: 'i-checks-sm',
large: 'i-checks-lg'
};
interface CheckboxProps {
id?: string;
key?: string | number;
style?: React.CSSProperties;
type?: string;
size?: 'sm' | 'lg' | 'small' | 'large';
label?: string;
labelClassName?: string;
className?: string;
onChange?: (value: any) => void;
value?: any;
containerClass?: string;
inline?: boolean;
trueValue?: boolean;
falseValue?: boolean;
disabled?: boolean;
readOnly?: boolean;
checked?: boolean;
name?: string;
description?: string;
classPrefix: string;
classnames: ClassNamesFn;
partial?: boolean;
data?: any;
id?: string;
key?: string | number;
style?: React.CSSProperties;
type?: string;
size?: 'sm' | 'lg' | 'small' | 'large';
label?: string;
labelClassName?: string;
className?: string;
onChange?: (value: any) => void;
value?: any;
containerClass?: string;
inline?: boolean;
trueValue?: boolean;
falseValue?: boolean;
disabled?: boolean;
readOnly?: boolean;
checked?: boolean;
name?: string;
description?: string;
classPrefix: string;
classnames: ClassNamesFn;
partial?: boolean;
data?: any;
}
export class Checkbox extends React.Component<CheckboxProps, any> {
static defaultProps = {
trueValue: true,
falseValue: false,
type: 'checkbox'
};
static defaultProps = {
trueValue: true,
falseValue: false,
type: 'checkbox'
};
@autobind
handleCheck(e: React.ChangeEvent<any>) {
const {trueValue, falseValue, onChange} = this.props;
@autobind
handleCheck(e: React.ChangeEvent<any>) {
const {trueValue, falseValue, onChange} = this.props;
if (!onChange) {
return;
}
onChange(e.currentTarget.checked ? trueValue : falseValue);
if (!onChange) {
return;
}
render() {
let {
size,
className,
classnames: cx,
value,
label,
partial,
trueValue,
children,
disabled,
description,
readOnly,
checked,
type,
name,
data,
labelClassName
} = this.props;
onChange(e.currentTarget.checked ? trueValue : falseValue);
}
className = (className ? className : '') + (size && sizeMap[size] ? ` ${sizeMap[size]}` : '');
render() {
let {
size,
className,
classnames: cx,
value,
label,
partial,
trueValue,
children,
disabled,
description,
readOnly,
checked,
type,
name,
data,
labelClassName
} = this.props;
return (
<label
className={cx(
`Checkbox Checkbox--${type}`,
{
'Checkbox--full': !partial
},
className
)}
>
<input
type={type}
checked={
typeof checked !== 'undefined'
? checked
: typeof value === 'undefined'
? value
: value == trueValue
}
onChange={this.handleCheck}
disabled={disabled}
readOnly={readOnly}
name={name}
/>
<i />
<span className={cx(labelClassName)}>{children || label}</span>
{description ? (<div className={cx("Checkbox-desc")}>{filter(description, data)}</div>) : null}
</label>
);
}
className =
(className ? className : '') +
(size && sizeMap[size] ? ` ${sizeMap[size]}` : '');
return (
<label
className={cx(
`Checkbox Checkbox--${type}`,
{
'Checkbox--full': !partial
},
className
)}
>
<input
type={type}
checked={
typeof checked !== 'undefined'
? checked
: typeof value === 'undefined'
? value
: value == trueValue
}
onChange={this.handleCheck}
disabled={disabled}
readOnly={readOnly}
name={name}
/>
<i />
<span className={cx(labelClassName)}>{children || label}</span>
{description ? (
<div className={cx('Checkbox-desc')}>{filter(description, data)}</div>
) : null}
</label>
);
}
}
export default themeable(Checkbox);

View File

@ -15,77 +15,98 @@ import {ClassNamesFn, themeable} from '../theme';
// import isPlainObject = require('lodash/isPlainObject');
export interface Option {
label?: string;
value?: any;
disabled?: boolean;
children?: Options;
description?: string;
[propName: string]: any;
label?: string;
value?: any;
disabled?: boolean;
children?: Options;
description?: string;
[propName: string]: any;
}
export interface Options extends Array<Option> {}
export interface OptionProps {
multi?: boolean;
multiple?: boolean;
valueField?: string;
options?: Options;
joinValues: boolean;
extractValue: boolean;
delimiter: string;
clearable: boolean;
placeholder?: string;
multi?: boolean;
multiple?: boolean;
valueField?: string;
options?: Options;
joinValues: boolean;
extractValue: boolean;
delimiter: string;
clearable: boolean;
placeholder?: string;
}
export type OptionValue = string | number | null | undefined | Option;
export function value2array(value: OptionValue | Array<OptionValue>, props: Partial<OptionProps>): Array<Option> {
if (props.multi || props.multiple) {
if (typeof value === 'string') {
value = value.split(props.delimiter || ',');
}
if (!Array.isArray(value)) {
if (value === null || value === undefined) {
return [];
}
value = [value];
}
return (value as Array<OptionValue>)
.map((value: OptionValue) =>
expandValue(
!props.joinValues && value && value.hasOwnProperty(props.valueField || 'value')
? (value as any)[props.valueField || 'value']
: value,
props
)
)
.filter((item: Option) => item) as Array<Option>;
export function value2array(
value: OptionValue | Array<OptionValue>,
props: Partial<OptionProps>
): Array<Option> {
if (props.multi || props.multiple) {
if (typeof value === 'string') {
value = value.split(props.delimiter || ',');
}
let expandedValue = expandValue(value as OptionValue, props);
return expandedValue ? [expandedValue] : [];
if (!Array.isArray(value)) {
if (value === null || value === undefined) {
return [];
}
value = [value];
}
return (value as Array<OptionValue>)
.map((value: OptionValue) =>
expandValue(
!props.joinValues &&
value &&
value.hasOwnProperty(props.valueField || 'value')
? (value as any)[props.valueField || 'value']
: value,
props
)
)
.filter((item: Option) => item) as Array<Option>;
}
let expandedValue = expandValue(value as OptionValue, props);
return expandedValue ? [expandedValue] : [];
}
export function expandValue(value: OptionValue, props: Partial<OptionProps>): Option | null {
const valueType = typeof value;
export function expandValue(
value: OptionValue,
props: Partial<OptionProps>
): Option | null {
const valueType = typeof value;
if (valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean' && valueType !== 'object') {
return null;
}
if (
valueType !== 'string' &&
valueType !== 'number' &&
valueType !== 'boolean' &&
valueType !== 'object'
) {
return null;
}
let {options, valueField} = props;
let {options, valueField} = props;
if (!options) {
return null;
}
if (!options) {
return null;
}
if (valueType === 'object' && value && value.hasOwnProperty(props.valueField || 'value')) {
value = (value as Option)[valueField || 'value'] || '';
}
if (
valueType === 'object' &&
value &&
value.hasOwnProperty(props.valueField || 'value')
) {
value = (value as Option)[valueField || 'value'] || '';
}
return find(flattenTree(options), item => isObject(value) ? item[valueField || 'value'] === value : String(item[valueField || 'value']) === String(value)) as Option;
return find(flattenTree(options), item =>
isObject(value)
? item[valueField || 'value'] === value
: String(item[valueField || 'value']) === String(value)
) as Option;
}
/**
@ -100,130 +121,143 @@ export function expandValue(value: OptionValue, props: Partial<OptionProps>): Op
* ]
*/
interface CheckboxesProps extends OptionProps {
id?: string;
key?: string;
className?: string;
type: string;
placeholder?: string;
disabled?: boolean;
value?: string;
onChange?: Function;
inline?: boolean;
columnsCount?: number;
checked?: boolean;
labelClassName?: string;
classPrefix: string;
classnames: ClassNamesFn;
id?: string;
key?: string;
className?: string;
type: string;
placeholder?: string;
disabled?: boolean;
value?: string;
onChange?: Function;
inline?: boolean;
columnsCount?: number;
checked?: boolean;
labelClassName?: string;
classPrefix: string;
classnames: ClassNamesFn;
}
export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
static defaultProps = {
joinValues: true,
extractValue: false,
inline: false,
delimiter: ',',
columnsCount: 1 // 一行显示一个
};
static defaultProps = {
joinValues: true,
extractValue: false,
inline: false,
delimiter: ',',
columnsCount: 1 // 一行显示一个
};
toggleOption(option: Option) {
const {value, onChange, joinValues, extractValue, delimiter, valueField, options} = this.props;
toggleOption(option: Option) {
const {
value,
onChange,
joinValues,
extractValue,
delimiter,
valueField,
options
} = this.props;
let valueArray = value2array(value, {
multiple: true,
valueField,
delimiter,
options
});
let idx = valueArray.indexOf(option);
let valueArray = value2array(value, {
multiple: true,
valueField,
delimiter,
options
});
let idx = valueArray.indexOf(option);
if (!~idx) {
option =
value2array(option[valueField || 'value'], {
multiple: true,
valueField,
delimiter,
options
})[0] || option;
idx = valueArray.indexOf(option);
}
if (~idx) {
valueArray.splice(idx, 1);
} else {
valueArray.push(option);
}
let newValue: string | Array<Option> = valueArray;
if (joinValues) {
newValue = newValue.map(item => item[valueField || 'value']).join(delimiter);
} else if (extractValue) {
newValue = newValue.map(item => item[valueField || 'value']);
}
onChange && onChange(newValue);
if (!~idx) {
option =
value2array(option[valueField || 'value'], {
multiple: true,
valueField,
delimiter,
options
})[0] || option;
idx = valueArray.indexOf(option);
}
render() {
const {
value,
valueField,
delimiter,
options,
className,
placeholder,
columnsCount,
disabled,
inline,
labelClassName
} = this.props;
let valueArray = value2array(value, {
multiple: true,
valueField,
delimiter,
options
});
let body: Array<React.ReactNode> = [];
if (options) {
body = options.map((option, key) => (
<Checkbox
key={key}
onChange={() => this.toggleOption(option)}
checked={!!~valueArray.indexOf(option)}
disabled={disabled || option.disabled}
inline={inline}
labelClassName={labelClassName}
>
{option.label}
</Checkbox>
));
}
if (!inline && (columnsCount as number) > 1) {
let cellClassName = `col-sm-${(12 / (columnsCount as number))
.toFixed(1)
.replace(/\.0$/, '')
.replace(/\./, '-')}`;
body = chunk(body, columnsCount).map((group, groupIndex) => (
<div className="row" key={groupIndex}>
{group.map((item, index) => (
<div key={index} className={cellClassName}>
{item}
</div>
))}
</div>
));
}
return <div className={className}>{body && body.length ? body : placeholder}</div>;
if (~idx) {
valueArray.splice(idx, 1);
} else {
valueArray.push(option);
}
let newValue: string | Array<Option> = valueArray;
if (joinValues) {
newValue = newValue
.map(item => item[valueField || 'value'])
.join(delimiter);
} else if (extractValue) {
newValue = newValue.map(item => item[valueField || 'value']);
}
onChange && onChange(newValue);
}
render() {
const {
value,
valueField,
delimiter,
options,
className,
placeholder,
columnsCount,
disabled,
inline,
labelClassName
} = this.props;
let valueArray = value2array(value, {
multiple: true,
valueField,
delimiter,
options
});
let body: Array<React.ReactNode> = [];
if (options) {
body = options.map((option, key) => (
<Checkbox
key={key}
onChange={() => this.toggleOption(option)}
checked={!!~valueArray.indexOf(option)}
disabled={disabled || option.disabled}
inline={inline}
labelClassName={labelClassName}
>
{option.label}
</Checkbox>
));
}
if (!inline && (columnsCount as number) > 1) {
let cellClassName = `col-sm-${(12 / (columnsCount as number))
.toFixed(1)
.replace(/\.0$/, '')
.replace(/\./, '-')}`;
body = chunk(body, columnsCount).map((group, groupIndex) => (
<div className="row" key={groupIndex}>
{group.map((item, index) => (
<div key={index} className={cellClassName}>
{item}
</div>
))}
</div>
));
}
return (
<div className={className}>
{body && body.length ? body : placeholder}
</div>
);
}
}
export default themeable(
uncontrollable(Checkboxes, {
value: 'onChange'
})
uncontrollable(Checkboxes, {
value: 'onChange'
})
);

View File

@ -7,98 +7,114 @@
import React from 'react';
import css = require('dom-helpers/style');
import {ClassNamesFn, themeable} from '../theme';
import Transition, {EXITED, ENTERING, EXITING} from 'react-transition-group/Transition';
import Transition, {
EXITED,
ENTERING,
EXITING
} from 'react-transition-group/Transition';
import {autobind} from '../utils/helper';
const collapseStyles: {
[propName: string]: string;
[propName: string]: string;
} = {
[EXITED]: 'out',
[EXITING]: 'out',
[ENTERING]: 'in'
[EXITED]: 'out',
[EXITING]: 'out',
[ENTERING]: 'in'
};
export interface CollapseProps {
show?: boolean;
mountOnEnter?: boolean;
unmountOnExit?: boolean;
className?: string;
classPrefix: string;
classnames: ClassNamesFn;
show?: boolean;
mountOnEnter?: boolean;
unmountOnExit?: boolean;
className?: string;
classPrefix: string;
classnames: ClassNamesFn;
}
export class Collapse extends React.Component<CollapseProps, any> {
static defaultProps: Pick<CollapseProps, 'show' | 'mountOnEnter' | 'unmountOnExit'> = {
show: false,
mountOnEnter: false,
unmountOnExit: false
};
static defaultProps: Pick<
CollapseProps,
'show' | 'mountOnEnter' | 'unmountOnExit'
> = {
show: false,
mountOnEnter: false,
unmountOnExit: false
};
contentDom: any;
contentRef = (ref: any) => (this.contentDom = ref);
contentDom: any;
contentRef = (ref: any) => (this.contentDom = ref);
@autobind
handleEnter(elem: HTMLElement) {
elem.style['height'] = null;
}
@autobind
handleEnter(elem: HTMLElement) {
elem.style['height'] = null;
}
@autobind
handleEntering(elem: HTMLElement) {
elem.style['height'] = `${elem['scrollHeight']}px`;
}
@autobind
handleEntering(elem: HTMLElement) {
elem.style['height'] = `${elem['scrollHeight']}px`;
}
@autobind
handleEntered(elem: HTMLElement) {
elem.style['height'] = null;
}
@autobind
handleEntered(elem: HTMLElement) {
elem.style['height'] = null;
}
@autobind
handleExit(elem: HTMLElement) {
let offsetHeight = elem['offsetHeight'];
const height = offsetHeight + parseInt(css(elem, 'marginTop'), 10) + parseInt(css(elem, 'marginBottom'), 10);
elem.style['height'] = `${height}px`;
@autobind
handleExit(elem: HTMLElement) {
let offsetHeight = elem['offsetHeight'];
const height =
offsetHeight +
parseInt(css(elem, 'marginTop'), 10) +
parseInt(css(elem, 'marginBottom'), 10);
elem.style['height'] = `${height}px`;
// trigger browser reflow
elem.offsetHeight;
}
// trigger browser reflow
elem.offsetHeight;
}
@autobind
handleExiting(elem: HTMLElement) {
elem.style['height'] = null;
}
@autobind
handleExiting(elem: HTMLElement) {
elem.style['height'] = null;
}
render() {
const {show, children, classnames: cx, mountOnEnter, unmountOnExit} = this.props;
render() {
const {
show,
children,
classnames: cx,
mountOnEnter,
unmountOnExit
} = this.props;
return (
<Transition
mountOnEnter={mountOnEnter}
unmountOnExit={unmountOnExit}
in={show}
timeout={300}
onEnter={this.handleEnter}
onEntering={this.handleEntering}
onEntered={this.handleEntered}
onExit={this.handleExit}
onExiting={this.handleExiting}
>
{(status: string) => {
if (status === ENTERING) {
this.contentDom.offsetWidth;
}
return React.cloneElement(children as any, {
...(children as React.ReactElement).props,
ref: this.contentRef,
className: cx(
'Collapse-content',
(children as React.ReactElement).props.className,
collapseStyles[status]
)
});
}}
</Transition>
);
}
return (
<Transition
mountOnEnter={mountOnEnter}
unmountOnExit={unmountOnExit}
in={show}
timeout={300}
onEnter={this.handleEnter}
onEntering={this.handleEntering}
onEntered={this.handleEntered}
onExit={this.handleExit}
onExiting={this.handleExiting}
>
{(status: string) => {
if (status === ENTERING) {
this.contentDom.offsetWidth;
}
return React.cloneElement(children as any, {
...(children as React.ReactElement).props,
ref: this.contentRef,
className: cx(
'Collapse-content',
(children as React.ReactElement).props.className,
collapseStyles[status]
)
});
}}
</Transition>
);
}
}
export default themeable(Collapse);

View File

@ -15,242 +15,256 @@ import PopOver from './PopOver';
import {ClassNamesFn, themeable} from '../theme';
export interface ColorProps {
placeholder?: string;
format: string;
// closeOnSelect:boolean;
clearable: boolean;
className?: string;
disabled?: boolean;
popOverContainer?: any;
placement?: string;
value: any;
classPrefix: string;
classnames: ClassNamesFn;
onChange: (value: any) => void;
presetColors?: string[];
placeholder?: string;
format: string;
// closeOnSelect:boolean;
clearable: boolean;
className?: string;
disabled?: boolean;
popOverContainer?: any;
placement?: string;
value: any;
classPrefix: string;
classnames: ClassNamesFn;
onChange: (value: any) => void;
presetColors?: string[];
}
export interface ColorControlState {
isOpened: boolean;
isFocused: boolean;
inputValue: string;
isOpened: boolean;
isFocused: boolean;
inputValue: string;
}
export class ColorControl extends React.PureComponent<ColorProps, ColorControlState> {
static defaultProps = {
format: 'hex',
clearable: true,
placeholder: '请选择颜色'
// closeOnSelect: true
};
state = {
isOpened: false,
isFocused: false,
inputValue: this.props.value || ''
};
popover: any;
closeTimer: number;
preview: React.RefObject<HTMLElement>;
input: React.RefObject<HTMLInputElement>;
constructor(props: ColorProps) {
super(props);
export class ColorControl extends React.PureComponent<
ColorProps,
ColorControlState
> {
static defaultProps = {
format: 'hex',
clearable: true,
placeholder: '请选择颜色'
// closeOnSelect: true
};
state = {
isOpened: false,
isFocused: false,
inputValue: this.props.value || ''
};
popover: any;
closeTimer: number;
preview: React.RefObject<HTMLElement>;
input: React.RefObject<HTMLInputElement>;
constructor(props: ColorProps) {
super(props);
this.open = this.open.bind(this);
this.close = this.close.bind(this);
this.focus = this.focus.bind(this);
this.blur = this.blur.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.clearValue = this.clearValue.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
this.handleClick = this.handleClick.bind(this);
this.preview = React.createRef();
this.input = React.createRef();
this.open = this.open.bind(this);
this.close = this.close.bind(this);
this.focus = this.focus.bind(this);
this.blur = this.blur.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.clearValue = this.clearValue.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
this.handleClick = this.handleClick.bind(this);
this.preview = React.createRef();
this.input = React.createRef();
}
componentWillReceiveProps(nextProps: ColorProps) {
const props = this.props;
if (props.value !== nextProps.value) {
this.setState({
inputValue: nextProps.value || ''
});
}
}
componentWillReceiveProps(nextProps: ColorProps) {
const props = this.props;
handleFocus() {
this.setState({
isFocused: true
});
}
if (props.value !== nextProps.value) {
this.setState({
inputValue: nextProps.value || ''
});
handleBlur() {
this.setState({
isFocused: false,
inputValue: this.props.value
});
}
focus() {
this.input.current && this.input.current.focus();
}
blur() {
this.input.current && this.input.current.blur();
}
open(fn?: () => void) {
if (this.props.disabled) {
return;
}
this.setState(
{
isOpened: true
},
fn
);
}
close() {
this.setState({
isOpened: false
});
}
clearValue() {
const onChange = this.props.onChange;
onChange('');
}
handleClick() {
this.state.isOpened ? this.close() : this.open(this.focus);
}
handleInputChange(e: React.ChangeEvent<HTMLInputElement>) {
const onChange = this.props.onChange;
this.setState(
{
inputValue: e.currentTarget.value
},
() => {
const dom: HTMLElement = this.preview.current as HTMLElement;
// 通过读取dom上到值确认当前输入值是否有效。
if (dom && dom.style.backgroundColor === this.state.inputValue) {
onChange(this.state.inputValue);
}
}
);
}
handleChange(color: ColorResult) {
const {
onChange,
format
// closeOnSelect
} = this.props;
if (format === 'rgba') {
onChange(
`rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`
);
} else if (format === 'rgb') {
onChange(`rgb(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b})`);
} else if (format === 'hsl') {
onChange(
`hsl(${Math.round(color.hsl.h)}, ${Math.round(
color.hsl.s * 100
)}%, ${Math.round(color.hsl.l * 100)}%)`
);
} else {
onChange(color.hex);
}
handleFocus() {
this.setState({
isFocused: true
});
}
// closeOnSelect && this.close();
}
handleBlur() {
this.setState({
isFocused: false,
inputValue: this.props.value
});
}
render() {
const {
classPrefix: ns,
className,
value,
placeholder,
disabled,
popOverContainer,
format,
clearable,
placement,
classnames: cx,
presetColors
} = this.props;
focus() {
this.input.current && this.input.current.focus();
}
const isOpened = this.state.isOpened;
const isFocused = this.state.isFocused;
blur() {
this.input.current && this.input.current.blur();
}
return (
<div
className={cx(
`ColorPicker`,
{
'is-disabled': disabled,
'is-focused': isFocused
},
className
)}
>
<input
size={10}
ref={this.input}
type="text"
autoComplete="off"
className={cx('ColorPicker-input')}
value={this.state.inputValue || ''}
placeholder={placeholder}
disabled={disabled}
onChange={this.handleInputChange}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
onClick={this.handleClick}
/>
open(fn?: () => void) {
if (this.props.disabled) {
return;
}
this.setState(
{
isOpened: true
},
fn
);
}
{clearable && !disabled && value ? (
<a onClick={this.clearValue} className={cx('ColorPicker-clear')}>
<Icon icon="close" className="icon" />
</a>
) : null}
close() {
this.setState({
isOpened: false
});
}
<span onClick={this.handleClick} className={cx('ColorPicker-preview')}>
<i
ref={this.preview}
className={`${ns}ColorPicker-previewIcon`}
style={{background: this.state.inputValue || '#ccc'}}
/>
</span>
clearValue() {
const onChange = this.props.onChange;
onChange('');
}
handleClick() {
this.state.isOpened ? this.close() : this.open(this.focus);
}
handleInputChange(e: React.ChangeEvent<HTMLInputElement>) {
const onChange = this.props.onChange;
this.setState(
{
inputValue: e.currentTarget.value
},
() => {
const dom: HTMLElement = this.preview.current as HTMLElement;
// 通过读取dom上到值确认当前输入值是否有效。
if (dom && dom.style.backgroundColor === this.state.inputValue) {
onChange(this.state.inputValue);
}
{isOpened ? (
<Overlay
placement={
placement || 'left-bottom-left-top right-bottom-right-top'
}
);
}
handleChange(color: ColorResult) {
const {
onChange,
format
// closeOnSelect
} = this.props;
if (format === 'rgba') {
onChange(`rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`);
} else if (format === 'rgb') {
onChange(`rgb(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b})`);
} else if (format === 'hsl') {
onChange(
`hsl(${Math.round(color.hsl.h)}, ${Math.round(color.hsl.s * 100)}%, ${Math.round(color.hsl.l * 100)}%)`
);
} else {
onChange(color.hex);
}
// closeOnSelect && this.close();
}
render() {
const {
classPrefix: ns,
className,
value,
placeholder,
disabled,
popOverContainer,
format,
clearable,
placement,
classnames: cx,
presetColors
} = this.props;
const isOpened = this.state.isOpened;
const isFocused = this.state.isFocused;
return (
<div
className={cx(
`ColorPicker`,
{
'is-disabled': disabled,
'is-focused': isFocused
},
className
)}
target={() => findDOMNode(this)}
onHide={this.close}
container={popOverContainer || (() => findDOMNode(this))}
rootClose={false}
show
>
<PopOver
classPrefix={ns}
className={cx('ColorPicker-popover')}
onHide={this.close}
overlay
>
<input
size={10}
ref={this.input}
type="text"
autoComplete="off"
className={cx('ColorPicker-input')}
value={this.state.inputValue || ''}
placeholder={placeholder}
disabled={disabled}
onChange={this.handleInputChange}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
onClick={this.handleClick}
/>
{clearable && !disabled && value ? (
<a onClick={this.clearValue} className={cx('ColorPicker-clear')}>
<Icon icon="close" className="icon" />
</a>
) : null}
<span onClick={this.handleClick} className={cx('ColorPicker-preview')}>
<i
ref={this.preview}
className={`${ns}ColorPicker-previewIcon`}
style={{background: this.state.inputValue || '#ccc'}}
/>
</span>
{isOpened ? (
<Overlay
placement={placement || 'left-bottom-left-top right-bottom-right-top'}
target={() => findDOMNode(this)}
onHide={this.close}
container={popOverContainer || (() => findDOMNode(this))}
rootClose={false}
show
>
<PopOver classPrefix={ns} className={cx('ColorPicker-popover')} onHide={this.close} overlay>
<SketchPicker
disableAlpha={!!~['rgb', 'hex'].indexOf(format as string)}
color={value}
presetColors={presetColors}
onChangeComplete={this.handleChange}
/>
</PopOver>
</Overlay>
) : null}
</div>
);
}
<SketchPicker
disableAlpha={!!~['rgb', 'hex'].indexOf(format as string)}
color={value}
presetColors={presetColors}
onChangeComplete={this.handleChange}
/>
</PopOver>
</Overlay>
) : null}
</div>
);
}
}
export default themeable(
uncontrollable(ColorControl, {
value: 'onChange'
})
uncontrollable(ColorControl, {
value: 'onChange'
})
);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More