@sunmi/mgt-app
TypeScript icon, indicating that this package has built-in type declarations

1.0.7 • Public • Published

以下内容按照字母表排序,无先后

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

待补充


app/ui

同antd、sunmi-ui

Readme

Keywords

Package Sidebar

Install

npm i @sunmi/mgt-app

Weekly Downloads

1

Version

1.0.7

License

ISC

Unpacked Size

594 kB

Total Files

392

Last publish

Collaborators

  • briefguo
  • liuwf
  • michel_ss