diff --git a/packages/plugin-settings-pane/src/setters/events-setter/event-dialog.tsx b/packages/plugin-settings-pane/src/setters/events-setter/event-dialog.tsx
new file mode 100644
index 000000000..7303f3649
--- /dev/null
+++ b/packages/plugin-settings-pane/src/setters/events-setter/event-dialog.tsx
@@ -0,0 +1,129 @@
+import { Component, isValidElement, ReactElement, ReactNode } from 'react';
+import { Dialog, Search, Input } from '@alifd/next';
+import './style.less';
+
+export default class EventDialog extends Component<{
+ dialigVisiable:?Boolean,
+ closeDialog:?()=>void,
+ submitDialog:?()=>void,
+ bindEventName:?String
+}> {
+
+ private eventList : Array = [
+ {
+ name: 'getData',
+ },
+ {
+ name: 'deleteData',
+ },
+ {
+ name: 'initData',
+ },
+ {
+ name: 'editData',
+ },
+ {
+ name: 'submitData'
+ },
+ ]
+
+ state = {
+ selectedEventName:'',
+ eventName:''
+ };
+
+ componentWillReceiveProps(nextProps){
+ this.setState({
+ eventName:nextProps.bindEventName
+ })
+ }
+
+ initEventName = () => {
+ const {bindEventName} = this.props;
+ let eventName = bindEventName;
+ this.eventList.map((item)=>{
+ if (item.name === eventName){
+ eventName = `${eventName}_new`;
+ }
+ })
+
+ this.setState({
+ eventName
+ })
+ }
+
+ onInputChange = (eventName:String) => {
+ this.setState({
+ eventName
+ })
+ }
+
+ onSelectItem = (eventName:String) => {
+ this.setState({
+ selectedEventName:eventName
+ })
+
+ // 为空是新建事件
+ if (eventName === ''){
+ this.initEventName()
+ }else{
+ this.setState({
+ selectedEventName:eventName,
+ eventName
+ })
+ }
+ }
+
+ onSearchEvent = (searchEventName:String) => {
+
+ }
+
+ onOk = () => {
+ this.props.submitDialog(this.state.eventName);
+ }
+
+
+ render() {
+ const { dialigVisiable, closeDialog} = this.props;
+ const {selectedEventName,eventName} = this.state;
+ return (
+
+ );
+ }
+}
diff --git a/packages/plugin-settings-pane/src/setters/events-setter/index.tsx b/packages/plugin-settings-pane/src/setters/events-setter/index.tsx
new file mode 100644
index 000000000..4aa1fc673
--- /dev/null
+++ b/packages/plugin-settings-pane/src/setters/events-setter/index.tsx
@@ -0,0 +1,408 @@
+import { Component, isValidElement, ReactElement, ReactNode } from 'react';
+import { Radio, Menu, Table, Icon, Dialog } from '@alifd/next';
+import { SettingField } from './main';
+import nativeEvents from './native-events';
+
+import './style.less';
+import EventDialog from './event-dialog';
+const { SubMenu, Item, Group, Divider } = Menu;
+const RadioGroup = Radio.Group;
+
+const EVENT_CONTENTS = {
+ COMPONENT_EVENT: 'componentEvent',
+ NATIVE_EVENT: 'nativeEvent',
+ LIFE_CYCLE_EVENT: 'lifeCycleEvent',
+};
+
+const DEFINITION_EVENT_TYPE = {
+ EVENTS: 'events',
+ NATIVE_EVENTS: 'nativeEvents',
+ LIFE_CYCLE_EVENT: 'lifeCycleEvent',
+};
+
+export default class EventsSetter extends Component<{
+ value: any[];
+ onChange: (eventList: any[]) => void;
+}> {
+ state = {
+ showEventList: false,
+ eventBtns: [],
+ eventList: [],
+ selectType: null,
+ nativeEventList: [],
+ lifeCycleEventList: [],
+ eventDataList: this.props.value || [],
+ isShowEventDialog: false,
+ bindEventName: '',
+ relatedEventName: '',
+ };
+
+ static getDerivedStateFromProps(nextProps, prevState) {
+ const { value } = nextProps;
+ if (value !== prevState.eventDataList) {
+ return {
+ value,
+ };
+ }
+ return null;
+ }
+
+ componentDidMount() {
+ this.initEventBtns();
+ this.initEventList();
+ }
+
+ /**
+ * 初始化事件按钮
+ */
+ initEventBtns() {
+ const { definition } = this.props;
+ let isRoot = false;
+ let isCustom = false;
+ let eventBtns = [];
+ definition.map(item => {
+ if (item.type === DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT) {
+ isRoot = true;
+ }
+
+ if (item.type === DEFINITION_EVENT_TYPE.EVENTS) {
+ isCustom = true;
+ }
+ });
+
+ if (isRoot) {
+ eventBtns = [
+ {
+ value: EVENT_CONTENTS.LIFE_CYCLE_EVENT,
+ label: '生命周期',
+ },
+ ];
+ } else if (isCustom) {
+ eventBtns = [
+ {
+ value: EVENT_CONTENTS.COMPONENT_EVENT,
+ label: '组件自带事件',
+ },
+ ];
+ } else {
+ eventBtns = [
+ {
+ value: EVENT_CONTENTS.NATIVE_EVENT,
+ label: '原生事件',
+ },
+ ];
+ }
+
+ this.setState({
+ eventBtns,
+ });
+ }
+
+ initEventList() {
+ const { definition } = this.props;
+ let nativeEventList = [];
+ definition.map(item => {
+ if (item.type === DEFINITION_EVENT_TYPE.EVENTS) {
+ this.checkEventListStatus(item.list, DEFINITION_EVENT_TYPE.EVENTS);
+ this.setState({
+ eventList: item.list,
+ });
+ }
+
+ if (item.type === DEFINITION_EVENT_TYPE.NATIVE_EVENTS) {
+ this.checkEventListStatus(
+ item.list,
+ DEFINITION_EVENT_TYPE.NATIVE_EVENTS,
+ );
+ nativeEventList = item.list;
+ }
+
+ if (item.type === DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT) {
+ this.checkEventListStatus(
+ item.list,
+ DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT,
+ );
+ this.setState({
+ lifeCycleEventList: item.list,
+ });
+ }
+ });
+
+ if (nativeEventList.length == 0) {
+ nativeEventList = nativeEvents;
+ this.setState({
+ nativeEventList,
+ });
+ }
+ }
+
+ checkEventListStatus = (eventList: Array, eventType: String) => {
+ const { eventDataList } = this.state;
+ if (
+ eventType === DEFINITION_EVENT_TYPE.EVENTS ||
+ eventType === DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT
+ ) {
+ eventList.map(item => {
+ item.disabled = false;
+ eventDataList.map(eventDataItem => {
+ if (item.name === eventDataItem.name) {
+ item.disabled = true;
+ }
+ });
+ });
+ } else if (eventType === DEFINITION_EVENT_TYPE.NATIVE_EVENTS) {
+ eventDataList.map(eventDataItem => {
+ eventList.map(item => {
+ item.eventList.map(eventItem => {
+ if (eventItem.name === eventDataItem.name) {
+ item.disabled = true;
+ } else {
+ item.disabled = false;
+ }
+ });
+ });
+ });
+ }
+ };
+
+ /**
+ * 渲染事件信息
+ */
+ renderEventInfoCell = (value, index, record) => {
+ let eventTagText = '';
+ if (record.type === EVENT_CONTENTS.NATIVE_EVENT) {
+ eventTagText = '原';
+ } else if (record.type === EVENT_CONTENTS.COMPONENT_EVENT) {
+ eventTagText = '组';
+ } else if (record.type === EVENT_CONTENTS.LIFE_CYCLE_EVENT) {
+ eventTagText = '生';
+ }
+ return (
+
+
+
{eventTagText}
+ {record.name}
+
+
+
+
+ {record.relatedEventName || ''}
+
+
+
+ );
+ };
+
+ /**
+ * 渲染事件操作项
+ */
+ renderEventOperateCell = (eventName: String) => {
+ return (
+
+ this.openDialog(eventName)}
+ />
+ this.openDeleteEventDialog(eventName)}
+ />
+
+ );
+ };
+
+ updateEventListStatus = (eventName: String, unDisabled: boolean) => {
+ const { eventList, nativeEventList, lifeCycleEventList } = this.state;
+ eventList.map(item => {
+ if (item.name === eventName) {
+ item.disabled = !unDisabled;
+ }
+ });
+
+ lifeCycleEventList.map(item => {
+ if (item.name === eventName) {
+ item.disabled = !unDisabled;
+ }
+ });
+
+ nativeEventList.map(item => {
+ item.eventList.map(itemData => {
+ if (itemData.name === eventName) {
+ itemData.disabled = !unDisabled;
+ }
+ });
+ });
+ };
+
+ onRadioChange = value => {
+ this.setState({
+ selectType: value,
+ });
+ };
+
+ onEventMenuClick = (eventName: String) => {
+ const { selectType, eventDataList } = this.state;
+ eventDataList.push({
+ type: selectType,
+ name: eventName,
+ });
+
+ this.setState({
+ eventDataList,
+ });
+
+ this.updateEventListStatus(eventName);
+ this.closeEventMenu();
+ this.openDialog(eventName);
+ };
+
+ closeEventMenu = () => {
+ if (this.state.selectType !== null) {
+ this.setState({
+ selectType: null,
+ });
+ }
+ };
+
+ openDeleteEventDialog = (eventName: String) => {
+ this.deleteEvent(eventName);
+ // Dialog.confirm({
+ // title: '删除事件',
+ // content: '确定删除当前事件吗',
+ // onOk: () => this.deleteEvent(eventName),
+ // });
+ };
+
+ deleteEvent = (eventName: String) => {
+ const { eventDataList } = this.state;
+ eventDataList.map((item, index) => {
+ if (item.name === eventName) {
+ eventDataList.splice(index, 1);
+ }
+ });
+
+ this.setState({
+ eventDataList,
+ });
+
+ this.updateEventListStatus(eventName, true);
+ };
+
+ openDialog = (bindEventName: String) => {
+ this.setState({
+ isShowEventDialog: true,
+ bindEventName,
+ });
+ };
+
+ closeDialog = () => {
+ this.setState({
+ isShowEventDialog: false,
+ });
+ };
+
+ submitDialog = (relatedEventName: String) => {
+ const { bindEventName, eventDataList } = this.state;
+ eventDataList.map(item => {
+ if (item.name === bindEventName) {
+ item.relatedEventName = relatedEventName;
+ }
+ });
+
+ this.props.onChange(eventDataList);
+
+ this.closeDialog();
+ };
+
+ render() {
+ const {
+ eventBtns,
+ eventList,
+ nativeEventList,
+ lifeCycleEventList,
+ selectType,
+ eventDataList,
+ isShowEventDialog,
+ bindEventName,
+ } = this.state;
+
+ let showEventList =
+ lifeCycleEventList.length > 0 ? lifeCycleEventList : eventList;
+ return (
+
+
+
+ {
+ eventBtns.length>1 ?点击选择事件类型:点击绑定事件
+ }
+
+
+
+ {selectType && selectType != EVENT_CONTENTS.NATIVE_EVENT && (
+
+ )}
+
+ {selectType && selectType === EVENT_CONTENTS.NATIVE_EVENT && (
+
+ )}
+
+
+
+
+
+ );
+ }
+}
diff --git a/packages/plugin-settings-pane/src/setters/events-setter/native-events.ts b/packages/plugin-settings-pane/src/setters/events-setter/native-events.ts
new file mode 100644
index 000000000..9bf6c5ae5
--- /dev/null
+++ b/packages/plugin-settings-pane/src/setters/events-setter/native-events.ts
@@ -0,0 +1,56 @@
+export default [
+ {
+ category: 'commonlyEvent',
+ name: '常用事件',
+ eventList: [
+ { name: 'onClick' },
+ { name: 'onChange' },
+ { name: 'onInput' },
+ { name: 'onSelect' },
+ { name: 'onSubmit' },
+ { name: 'onReset' },
+ { name: 'onFocus' },
+ { name: 'onBlur' },
+ { name: 'onScroll' },
+ { name: 'onLoad' },
+ { name: 'onError' },
+ ],
+ },
+ {
+ category: 'keybordEvent',
+ name: '键盘事件',
+ eventList: [{ name: 'onKeyDown' }, { name: 'onKeyPress' }, { name: 'onKeyUp' }],
+ },
+ {
+ category: 'mouseEvent',
+ name: '鼠标事件',
+ eventList: [
+ { name: 'onDoubleClick' },
+ { name: 'onDrag' },
+ { name: 'onDragEnd' },
+ { name: 'onDragEnter' },
+ { name: 'onDragExit' },
+ { name: 'onDragLeave' },
+ { name: 'onDragOver' },
+ { name: 'onDragStart' },
+ { name: 'onDrop' },
+ { name: 'onMouseDown' },
+ { name: 'onMouseEnter' },
+ { name: 'onMouseLeave' },
+ { name: 'onMouseMove' },
+ { name: 'onMouseOut' },
+ { name: 'onMouseOver' },
+ { name: 'onMouseUp' },
+ ],
+ },
+ {
+ category: 'animateEvent',
+ name: '动画事件',
+ eventList: [
+ { name: 'onAnimationStart' },
+ { name: 'onAnimationEnd' },
+ { name: 'onAnimationItration' },
+ { name: 'onTransitionEnd' },
+ ],
+ },
+];
diff --git a/packages/plugin-settings-pane/src/setters/events-setter/style.less b/packages/plugin-settings-pane/src/setters/events-setter/style.less
new file mode 100644
index 000000000..625129486
--- /dev/null
+++ b/packages/plugin-settings-pane/src/setters/events-setter/style.less
@@ -0,0 +1,155 @@
+.event-body {
+ padding: 0 10px 0 10px;
+ position: relative;
+ min-height: 450px;
+
+ .event-title {
+ height: 30px;
+ line-height: 30px;
+ margin-bottom: 10px;
+ }
+
+
+ .next-radio-group {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ }
+
+ .next-radio-group label {
+ -webkit-box-flex: 1;
+ -webkit-flex: auto;
+ -ms-flex: auto;
+ flex: auto;
+ text-align: center;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+
+
+ .event-cell {
+ padding-left: 25px;
+ position: relative;
+ font-size: 12px;
+ }
+
+ .event-type-tag {
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ left: 0px;
+ top: -2px;
+ border-radius: 50%;
+ line-height: 20px;
+ text-align: center;
+ color: #ffffff;
+ background-color: #2077ff;
+ }
+
+ .related-icon {
+ margin-right: 5px;
+ }
+
+ .related-event-name {
+ color: #2077ff;
+ cursor: pointer;
+ }
+
+
+ .event-menu {
+ max-height: 300px;
+ width: 230px;
+ overflow-x: hidden;
+ position: absolute;
+ top: 67px;
+ left: 10px;
+ z-index: 10;
+ }
+
+ .event-table {
+ margin-top: 20px;
+ }
+
+ .event-operate-icon {
+ cursor: pointer;
+ }
+
+ .event-operate-icon:hover {
+ color: #0079f2;
+ }
+}
+
+
+.event-dialog-body {
+ width: 800px;
+ height: 450px;
+
+
+ .dialog-small-title {
+ font-weight: 700;
+ margin-bottom: 8px;
+ color: rgba(0, 0, 0);
+ }
+
+ .dialog-left-container {
+ float: left;
+
+ .dialog-left-context {
+ width: 268px;
+ height: 392px;
+ border: 1px solid rgba(31, 56, 88, .3);
+ border-radius: 3px;
+
+ .event-type-container {
+ width: 110px;
+ height: 390px;
+ border-right: 1px solid rgba(31, 56, 88, .3);
+ float: left;
+ }
+
+ .select-item {
+ font-size: 12px;
+ height: 28px;
+ line-height: 28px;
+ padding: 0 30px 0 12px;
+ cursor: pointer;
+ position: relative;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .select-item-active {
+ background: rgba(31, 56, 88, .06);
+ }
+
+ .event-select-container {
+ width: 156px;
+ float: left;
+
+ .event-search-box {
+ width: 135px;
+ margin: 10px;
+ }
+ }
+
+ .event-list {
+ overflow-y: auto;
+ overflow-x: hidden;
+ height: 342px;
+ }
+ }
+ }
+
+ .dialog-right-container {
+ width: 530px;
+ padding-left: 20px;
+ float: left;
+
+ .event-input-container {
+ margin-bottom: 20px;
+ }
+ }
+}
diff --git a/packages/plugin-settings-pane/src/setters/locale/snippets.js b/packages/plugin-settings-pane/src/setters/locale/snippets.js
new file mode 100644
index 000000000..7c8484c4f
--- /dev/null
+++ b/packages/plugin-settings-pane/src/setters/locale/snippets.js
@@ -0,0 +1,242 @@
+export default [
+ {
+ label: 'constants',
+ kind: 'Class',
+ insertText: 'constants',
+ detail: '应用全局常量',
+ documentation: '应用范围定义的通用常量'
+ },
+ {
+ label: 'utils',
+ kind: 'Class',
+ insertText: 'utils',
+ detail: '应用全局公共函数',
+ documentation: '应用范围扩展的公共函数'
+ },
+ {
+ label: 'state',
+ kind: 'Enum',
+ insertText: 'state',
+ detail: '当前所在容器组件内部状态',
+ documentation: 'React Class内部状态state'
+ },
+ {
+ label: 'setState',
+ kind: 'Function',
+ insertText: 'setState({\n\t$0\n})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: '设置当前所在容器组件的state数据',
+ documentation: '原生React方法,会自动更新组件视图'
+ },
+ {
+ label: 'reloadDataSource',
+ kind: 'Function',
+ insertText: 'reloadDataSource(${1:${2:namespace}, ${3:false}, ${4:callback}})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: '刷新当前所在的容器组件',
+ documentation: '触发当前所在的容器组件,重新发送异步请求,并用最新数据更新视图'
+ },
+ {
+ label: 'location',
+ kind: 'Class',
+ insertText: 'location',
+ detail: '路由解析对象'
+ },
+ {
+ label: 'location.query',
+ kind: 'Value',
+ insertText: 'location.query.${1:xxxx}',
+ insertTextRules: 'InsertAsSnippet',
+ detail: '从路由解析对象中获取参数信息'
+ },
+ {
+ label: 'history',
+ kind: 'Class',
+ insertText: 'history',
+ detail: '路由历史对象'
+ },
+ {
+ label: 'React',
+ kind: 'Keyword',
+ insertText: 'React',
+ detail: 'React对象'
+ },
+ {
+ label: 'ReactDOM',
+ kind: 'Keyword',
+ insertText: 'ReactDOM',
+ detail: 'ReactDom对象'
+ },
+ {
+ label: 'ReactDOM.findDOMNode',
+ kind: 'Function',
+ insertText: 'ReactDOM.findDOMNode(${1:this.refs.xxxx})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: 'ReactDom查找真实dom node'
+ },
+ {
+ label: 'Dialog.alert',
+ kind: 'Method',
+ insertText: [
+ 'Dialog.alert({',
+ "\tcontent: '${1:Alert content}',",
+ "\ttitle: '${2:Title}',",
+ '\tonOk: () => {',
+ '\t\t$3',
+ '\t}',
+ '})'
+ ].join('\n'),
+ insertTextRules: 'InsertAsSnippet',
+ detail: 'alert弹框 By Fusion'
+ },
+ {
+ label: 'Dialog.confirm',
+ kind: 'Method',
+ insertText: [
+ 'Dialog.confirm({',
+ "\tcontent: '${1:Confirm content}',",
+ "\ttitle: '${2:Title}',",
+ '\tonOk: () => {',
+ '\t\t$3',
+ '\t},',
+ '\tonCancel: () => {',
+ '\t\t$4',
+ '\t}',
+ '})'
+ ].join('\n'),
+ insertTextRules: 'InsertAsSnippet',
+ detail: '确认弹出框 By Fusion'
+ },
+ {
+ label: 'Message.success',
+ kind: 'Method',
+ insertText: 'Message.success(${1:content})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: '成功反馈提示 By Fusion'
+ },
+ {
+ label: 'Message.error',
+ kind: 'Method',
+ insertText: 'Message.error(${1:content})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: '错误反馈提示 By Fusion'
+ },
+ {
+ label: 'Message.help',
+ kind: 'Method',
+ insertText: 'Message.help(${1:content})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: '帮助反馈提示 By Fusion'
+ },
+ {
+ label: 'Message.loading',
+ kind: 'Method',
+ insertText: 'Message.loading(${1:content})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: 'loading反馈提示 By Fusion'
+ },
+ {
+ label: 'Message.notice',
+ kind: 'Method',
+ insertText: 'Message.notice(${1:content})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: '注意反馈提示 By Fusion'
+ },
+ {
+ label: 'Message.waining',
+ kind: 'Method',
+ insertText: 'Message.waining(${1:content})',
+ insertTextRules: 'InsertAsSnippet',
+ detail: '警告反馈提示 By Fusion'
+ },
+ {
+ label: 'Modal.confirm',
+ kind: 'Method',
+ insertText: [
+ 'Modal.confirm({',
+ "\tcontent: '${1:Confirm content}',",
+ "\ttitle: '${2:Title}',",
+ '\tonOk: () => {',
+ '\t\t$3',
+ '\t},',
+ '\tonCancel: () => {',
+ '\t\t$4',
+ '\t}',
+ '})'
+ ].join('\n'),
+ insertTextRules: 'InsertAsSnippet',
+ detail: '确认弹出框 By Antd'
+ },
+ {
+ label: 'Modal.info',
+ kind: 'Method',
+ insertText: [
+ 'Modal.info({',
+ "\tcontent: '${1:Info content}',",
+ "\ttitle: '${2:Title}',",
+ '\tonOk: () => {',
+ '\t\t$3',
+ '\t},',
+ '\tonCancel: () => {',
+ '\t\t$4',
+ '\t}',
+ '})'
+ ].join('\n'),
+ insertTextRules: 'InsertAsSnippet',
+ detail: '信息弹出框 By Antd'
+ },
+ {
+ label: 'Modal.success',
+ kind: 'Method',
+ insertText: [
+ 'Modal.success({',
+ "\tcontent: '${1:Success content}',",
+ "\ttitle: '${2:Title}',",
+ '\tonOk: () => {',
+ '\t\t$3',
+ '\t},',
+ '\tonCancel: () => {',
+ '\t\t$4',
+ '\t}',
+ '})'
+ ].join('\n'),
+ insertTextRules: 'InsertAsSnippet',
+ detail: '成功弹出框 By Antd'
+ },
+ {
+ label: 'Modal.error',
+ kind: 'Method',
+ insertText: [
+ 'Modal.error({',
+ "\tcontent: '${1:Error content}',",
+ "\ttitle: '${2:Title}',",
+ '\tonOk: () => {',
+ '\t\t$3',
+ '\t},',
+ '\tonCancel: () => {',
+ '\t\t$4',
+ '\t}',
+ '})'
+ ].join('\n'),
+ insertTextRules: 'InsertAsSnippet',
+ detail: '错误弹出框 By Antd'
+ },
+ {
+ label: 'Modal.warning',
+ kind: 'Method',
+ insertText: [
+ 'Modal.warning({',
+ "\tcontent: '${1:Warning content}',",
+ "\ttitle: '${2:Title}',",
+ '\tonOk: () => {',
+ '\t\t$3',
+ '\t},',
+ '\tonCancel: () => {',
+ '\t\t$4',
+ '\t}',
+ '})'
+ ].join('\n'),
+ insertTextRules: 'InsertAsSnippet',
+ detail: '警告弹出框 By Antd'
+ }
+];
\ No newline at end of file
diff --git a/packages/plugin-settings-pane/src/setters/locale/utils.js b/packages/plugin-settings-pane/src/setters/locale/utils.js
new file mode 100644
index 000000000..a02a8dd06
--- /dev/null
+++ b/packages/plugin-settings-pane/src/setters/locale/utils.js
@@ -0,0 +1,21 @@
+import IntlMessageFormat from 'intl-messageformat';
+
+export const isJSExpression = (obj = '') => {
+ if(obj && typeof obj === 'object' && obj.type === 'JSExpression') {
+ return true;
+ }
+ return false;
+}
+
+/**
+ * 用于构造国际化字符串处理函数
+ * @param {*} locale 国际化标识,例如 zh-CN、en-US
+ * @param {*} messages 国际化语言包
+ */
+export const generateI18n = (locale = 'zh-CN', messages = {}) => {
+ return function (key, values = {}) {
+ if (!messages || !messages[key]) return '';
+ const formater = new IntlMessageFormat(messages[key], locale);
+ return formater.format(values);
+ };
+}
diff --git a/packages/plugin-settings-pane/src/setters/locale/zh-CN.js b/packages/plugin-settings-pane/src/setters/locale/zh-CN.js
new file mode 100644
index 000000000..951596009
--- /dev/null
+++ b/packages/plugin-settings-pane/src/setters/locale/zh-CN.js
@@ -0,0 +1,36 @@
+export default {
+ // function
+ setting: '点击设置',
+ edit: '编辑',
+ submitConfirm: '确认提交 cmd+s',
+ close: '关闭 esc',
+ fullScreen: '全屏',
+ cancelFullScreen: '取消全屏',
+ jsonIllegal: '非json格式',
+ functionIllegal: '非function格式',
+ objectIllegal: '非object格式',
+ circularRef: '对象中出现循环引用的对象',
+ formatError: '格式错误',
+ saved: '已保存',
+ // expression
+ valueIllegal: '值类型为对象类型,与当前组件属性设置的控件类型不匹配,请在属性“代码编辑模式”下进行编辑',
+ jsExpression: '请输入JS表达式',
+ // Mixin
+ input: '字符串Input',
+ textarea: '多行字符串Textarea',
+ expression: '变量控件Expression',
+ monacoEditor: '编辑器MonacoEditor',
+ numberPicker: '数字NumberPicker',
+ bool: '布尔Switch',
+ datePicker: '日期选择DatePicker',
+ select: '下拉选择Select',
+ radio: '单项选择RadioGroup',
+ date: '日期选择DatePicker',
+ dateYear: '年选择DatePicker',
+ dateMonth: '月选择DatePicker',
+ dateRange: '日期区间选择DatePicker',
+ list: '数组List',
+ object: '对象ObjectButton',
+ reactNode: '节点类型ReactNode',
+ typeError: 'Minix组件属性Types配置错误,存在不支持类型[{type}],请检查组件属性配置',
+};
\ No newline at end of file