@sunmi/mgt-app
v1.0.7
Published
<!-- app使用说明 --> 以下内容按照字母表排序,无先后
Downloads
3
Readme
以下内容按照字母表排序,无先后
app/editor
- 基于draftJS的编辑器,为满足商品详情编辑的基本需求
- 支持撤销重做、标题、加粗、斜体、下划线、添加链接、上传视频、上传图片等
- 始终是一个受控组件,必须指定editorState和onChange
在简单的业务场景
import { convertRawContentStateToEditorState, DraftEditor, EditorState } from 'app/editor';
import React from 'react';
export default class Editor extends React.Component {
state = {
editorState: EditorState.createEmpty(),
};
render() {
return (
<div style={{ width: 800, padding: 40 }}>
<DraftEditor
editorState={this.state.editorState}
onChange={this.handleChange}
/>
</div>
);
}
handleChange = (editorState: EditorState) => {
// this.props.onChange(editorState);
this.setState({ editorState });
}
}
复杂完整的业务场景
addImage?: (file: File)=> string | Promise<string>
addVideo?: (file: File)=> string | Promise<string>
可选,添加方法后,编辑器的工具栏才会有添加图片、添加视频按钮
import { convertRawContentStateToEditorState, DraftEditor, EditorState } from 'app/editor';
import { fetchWebapi } from 'app/fetch';
import { Spin } from 'app/ui';
import videoUtils from 'lib/uploadVideo';
import React from 'react';
export default class Editor extends React.Component {
state = {
editorState: EditorState.createEmpty(),
spining: false,
spinTip: ''
};
static getDerivedStateFromProps(props: any, state: any) {
if (props.value instanceof EditorState) {
const editorState = props.value;
return {
editorState
};
} else if (props.value instanceof Object) {
const editorState = convertRawContentStateToEditorState(props.value);
return {
editorState
};
} else {
return null;
}
}
render() {
return (
<div style={{ width: 800, padding: 40 }}>
<Spin spinning={this.state.spining} tip={this.state.spinTip}>
<DraftEditor
editorState={this.state.editorState}
onChange={this.handleChange}
addImage={this.addImage}
addVideo={this.addVideo}
/>
</Spin>
</div>
);
}
handleChange = (editorState: EditorState) => {
// this.props.onChange(editorState);
this.setState({ editorState });
}
addImage = async (file: File) => {
// 上传到服务器
this.setState({ spining: true, spinTip: '图片上传中...' });
const formdata = new FormData();
formdata.append('file', file);
const { data } = await fetchWebapi('/webapi/misun/web/file/1.0/?service=File.uploadPicture', { body: { file }, method: 'POST' })
.then(res => res.json());
this.setState({ spining: false });
return data.url;
}
addVideo = async (file: File) => {
return new Promise((resolve: (url: string) => void) => {
videoUtils.uploadVideo({
file,
onProgress: async (percent: number) => {
this.setState({ spining: true, spinTip: `视频上传中${percent}` });
},
onChange: (data: { url: string, screenshot_pic: string }) => {
resolve(data.url);
this.setState({ spining: false });
}
});
});
}
}
app/env 环境变量
使用
// 环境变量汇总
import { envHost, isEncrypted, md5Key, SUNMI_REMOTESERVER } from 'app/env';
SUNMI_ENV:string
环境标识,分dev、test、uat、cte、prod等环境
envHost: (host:string) => string
// 生成环境主机名,例如
envHost('webapi.sunmi.com')
// SUNMI_ENV=dev,=> '//webapi.dev.sunmi.com'
// SUNMI_ENV=test,=> '//webapi.test.sunmi.com'
// SUNMI_ENV=uat,=> '//webapi.uat.sunmi.com'
// SUNMI_ENV=prod,=> '//webapi.sunmi.com'
isEncrypted:boolean
获取当前环境是否加密
md5Key:string
获取当前环境的md5key
DES:{ Key:string, Iv:string }
获取当前环境的DES的Key、Iv
NODE_HOST:string
同SUNMI_ENV,推荐使用SUNMI_ENV
NODE_ENV: 'development' | 'production'
区分开发和生产
defaultHost:string
获取默认接口环境
SUNMI_REMOTESERVER:string
远端tool服务器
app/events
使用
dispatchEvent: (eventName:string, detail:any) => void
onEvent: (eventName:string) => Observable<any>
app/form
使用
- 重定义了Form.create()
- 新增this.props.form.createField方法和支持配置写法
- TS类型支持
import { createForm, FormComponentProps } from 'app/form';
import { Input } from 'app/ui'
// ...
@createForm({
fieldConfigs: [{
id: 'goods_title',
fieldOptions: {
rules: [{ required: true, message: '请输入商品名称' }]
},
component: { use: Input, mapPropsToExtraProps: (props) => ({}) },
formItemProps: { label: '商品名称', },
}],
mapPropsToFields: (props: EditGoodFormProps) => {
return { ...props.value };
}
})
class EditGoodForm extends React.Component<EditGoodFormProps> {
render() {
const GoodsTitle = this.props.form.createField('goods_title')
// => this.props.form.getFieldDecorator('goods_title',...)(<Input />)
return (
<div>{GoodsTitle}</div>
)
}
}
app/operators
keyBy: (collection:object[], reg:string) => object
列表转对象的方法
keyBy([{x:1,y:2},{x:3,y:2}],'x:_self')
// =>{ 1:{x:1,y:2}, 3:{x:3,y:2} }
keyBy([{x:1,y:2},{x:3,y:2}],'x:y')
// =>{ 1:2, 3:2 }
app/private
私有部分
待补充
app/promise
对未Promise化的 Web API进行Promise化,比如:FileReader
app/providers
MobxProvider: React.Component
interface MobxProviderProps {
stores?: PromiseComponentMap;
withGlobalList?: boolean;
children: any;
}
import { MobxProvider } from 'app/providers';
import { LoadableRoute as Route, Switch } from 'app/router';
import React from 'react';
export default class GoodsManageNewModule extends React.Component {
render() {
return (
<MobxProvider stores={{ GoodsManageNewStore: () => import('./stores/goodsManage') }}>
<Switch>
<Route exact={true} path="/ts-mobx-realworld" loader={() => import('./containers/GoodsList')} />
<Route path="/ts-mobx-realworld/addGoods/:gId?" loader={() => import('./containers/AddGoods')} />
<Route path="/ts-mobx-realworld/edit/:gId?" loader={() => import('./containers/Edit')} />
</Switch>
</MobxProvider>
);
}
}
ReduxProvider: React.Component
interface ReduxProviderProps {
sagas?: any;
reducers?: ReducersMapObject;
withGlobalList?: boolean;
namespace: string;
actions?: any;
actionTypes?: any;
children: any;
}
import * as Actions from './actions';
import * as actionTypes from './actionTypes';
import * as reducers from './reducers';
import { ReduxProvider } from 'app/providers';
import { LoadableRoute as Route, Redirect, Switch } from 'app/router';
import React from 'react';
export default class TsReduxModule extends React.Component {
render() {
return (
<ReduxProvider namespace="financial" actions={Actions} reducers={reducers} actionTypes={actionTypes}>
<Switch>
<Redirect exact={true} from="/ts-redux" to="/ts-redux/settlement" />
<Route exact={true} path="/ts-redux/settlement" loader={() => import('./containers/Settlement')} />
<Route path="/ts-redux/settlement/detail/:settleParam" loader={() => import('./containers/SettlementDetail')} />
</Switch>
</ReduxProvider>
);
}
}
BreadcrumbProvider
import { Breadcrumb, registerBreadcrumb } from 'app/providers';
import React from 'react';
import './hello.css';
@registerBreadcrumb({
render: () => (
<Breadcrumb>
<Breadcrumb.Back />
<Breadcrumb.Item to="/xxx">ts-mobx-hello</Breadcrumb.Item>
<Breadcrumb.Item>hello world</Breadcrumb.Item>
</Breadcrumb>
)
})
export default class TsMobxHello extends React.Component {
render() {
// ...
}
}
app/router
待补充
app/services
待补充