npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@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

待补充


app/ui

同antd、sunmi-ui