# amos-framework

## useage

```bash
  npm i --save amos-framework
```

属性说明：部分组件属性列表中如果未写入 `className 、style` 等原始属性， 默认情况下，其组件均已内部支持，按规范传入组件属性即可。

### the components list

```js
Avatar,
Badge,
Button,

AddFrame,
CardItem,
CardFrame,

CardPane,

Row,
Col,
Layout,

Input,
InputNumber,
Search,
Totop,
Menu,
NestedMenu,
message,
FlashNotice,
Toast,
Tips,
Modal,

Nav,
NavItem,
IndexNavItem,
DropNav,

List,
NavTab,
Popover,
Overlay,
Scrollbars,
ScrollingLoad,

Spin,
NestedSpin,
SingleSpin,

Steps,
Switch,
Tabs,
ComplexTab,

Tag,
CheckableTag,
TagSelect,

Timeline,
Tooltip,
Transfer,
Divider,
Breadcrumb,
Collapse,
Form,
Checkbox,
Radio,
Carousel,
Dropdown,
Rate,
Slider,
Panel,
Select,
MultiSelect,
Cascader,
Tree,
Upload,
Progress,
Pagination,
Anchor,

// ext
Editable,
ClearableInput,
CopyToClipboard,
HelpTip,
Paragraph,
EmptyData,
User,
Affix,
Shuttle,
BuckleDropdown,
Verifycode,
Waves,

IFrame,
Bullet,
Icon,
Group,

// tools
UploadModal,
FormTip,
ChartTheme,
MailToBtn,
PhoneCallBtn,
Base64Image,
InputFile,
TimeNow,
JsonView,
AutoComplete,
Drawer,
SidePane,
MovablePane,
SplitPane,
Marquee,
Fragment,
DomTitle,

// other
Portal,
DownloadBrowsers,
Animate,
OverFlowText,
ScrollText,
FormBuilder,
StdForm,
StdFormRow,
FormGroup,
FormLink,
SlideCode,
ContextMenu,

// property
Property,

// unreact
AmosAlert,
// render
PureRenderMixin,
Connect,
ColorPicker, DropColor, CustomColor,

// pages

Version
```

## methods

提供的基本方法、工具说明

```js
// 该方法，匹配的child节点，可设置 `__AMOS_TYPE__` 用于匹配，默认 采用 `displayName、name` 进行匹配
// 优先级 __AMOS_TYPE__ > displayName > name
// 当基础组件被编译之后，如果不手动提供 __AMOS_TYPE__ 和 displayName 时，采用 name 进行 type 匹配，将会出现匹配异常。
findAllByType(children, type);

// example

const MyButton = (props) => <Button {...props}/>;
// 设置 __AMOS_TYPE__ 为 Button 以确保，可以作为 ButtonGroup 等组件的子组件使用
MyButton.__AMOS_TYPE__ = 'Button';
```

## 添加 sdk license

步骤：

第一步：从 `amos-authorization` 库中，将 `lib/licenseSdk.js` 拷贝至根目录

第二步：执行 `npm run dist` 即可生成带有 license 的完整包，目录在 dist 目录下，其它系统，引入包时，可通过 html 页面直接嵌入，如：

```html
<script src="/node_modules/react/umd/react.development.js"></script>
<script src="/node_modules/react-dom/umd/react-dom.development.js"></script>
<script src="/extra/amosframework/amosframework.min.js"></script>
<link rel="stylesheet" href="/extra/amosframework/amosframework.min.css">
```

第三步：修改 `webpack` 配置文件，添加如下代码：

```js
webpackConfig.externals = {
  'react': 'React',
  'react-dom': 'ReactDOM',
  'amos-framework': 'amosframework'
};
```

> license 使用教程

一下方式均可：

1. 直接在项目服务器根目录放置 `license.dat`
2. 直接在window对象上设置 `__amos__license__`，值可以是 string 类型，也可以是 object类型

```js
window.__amos__license__ = `
licenseVersion=
licenseType=
permissionList=a,b,a,c,d
beginDate=
endDate=
macAddress=
licenseDescr=
signature=
`;

// or
window.__amos__license__ = {
  licenseVersion: '',
  licenseType: '',
  permissionList: 'a,b,a,c,d',
  beginDate: '',
  endDate: '',
  macAddress: '',
  licenseDescr: '',
  signature: ''
};

// 快速开启 dev
window.__amos__license__ = 'test';
```

## 按需加载模块

按需加载，依赖于 `ray-pack-toolkit/lib/babel/SplitImportPlugin`

方法一： 创建 `amos-framework` 特有的按需加载 `babel` 插件

```js
// AFImportPlugin.js
import { getSplitImportPlugin } from 'ray-pack-toolkit/lib/babel/SplitImportPlugin';
import moduleMapping from 'amos-framework/lib/moduleMapping';

module.exports = getSplitImportPlugin({
  'amos-framework': moduleMapping
});

// 使用
// .babelrc
{
  ...
  "plugins":[
    ["./AFImportPlugin", { "libraryName": "amos-framework" }]
  ]
}

// 或者直接在 amos-build 中使用, 支持的方式： `simpleConfig/umdConfig/docitConfig/cjsLibConfig`
const config = {
  babelPlugin: './AFImportPlugin'
};

// amos-build 中使用内置 plugin
import moduleMapping from 'amos-framework/lib/moduleMapping';

// or
// 采用 require 的方式引入
const _moduleMapping = require('amos-framework/lib/moduleMapping');
const moduleMapping = _moduleMapping.default ? _moduleMapping.default : _moduleMapping;

const config = {
  babelPlugin: [
    ['ray-pack-toolkit/lib/babel/SplitImportPlugin', {
      "libraryName": "amos-framework",
      "customMapping": {
        'amos-framework': moduleMapping
      }
    }]
  ]
};
```

## 自定义主题步骤

通过修改系统默认色，统一调整所有组件的基调

- index.scss

```scss
$font-size: 12px;
$primary-color: #345fa6;
$primary-color-deep: #1a4fa3;
$primary-color-deeper: #0f4aaa;

$success-color: #4cd964;
$danger-color: #f94242;
$warning-color: #faad14;
$error-color: #f5222d;

$background-color: #203957;

@import '~amos-framework/lib/styles/useTheme.scss';
// 独立加入 icon
@import '~amos-framework/lib/styles/fonts/iconfont.css';
```

- entry.js

```js
import './index.scss';
```

- webpack.config.js

```js
const themeConfig = require('amos-build/lib/themeConfig');

module.exports = themeConfig({
  entry: {
    amosframework: './index.js'
  }
});
```

- package.json

```json
{
  ...
  "scripts": {
  ...
  "build": "set NODE_ENV=production && rimraf dist && webpack",
  ...
  }
  ...
}
```

执行 `npm run build` 即可生成新的主题。 创建完主题之后，将默认引入的 `amos-framework/dist/amosframework.css` 改为 自定义的主题 `css` 文件即可。

## 通过 CSS 变量改变全局色系

since v1.7.0 版本，将系统主颜色，交由css变量控制，可通过如下方式，控制全局颜色。

* 该方法只需要执行一次，如果多个系统中，均存在执行该方法，则以最后执行的为主。
* 建议在主系统入口处执行该方法。
* 如果通过该方法控制系统主题色的变化，可以在具体的方法体中执行，或交由系统最顶层加载时统一处理

```js
import { CSSVarUtils } from 'amos-framework';

CSSVarUtils.changePrimaryColor('#1d5cb8');
```

## MicroApp 使用

在 `plugins` 中直接加入

```js
import { MicroApp } from 'amos-framework';
import { history } from 'amos-designer';

const plugins = [
  ...,
  { path: 'home', component: Home },
  ...,
  MicroApp.getMicroAppByIframe({
    path: 'myrule',
    url(){
      const token = getToken();
      const _url = `${outterURI.activitiURI}/myrule?token=${token}`;
      return history.urlpath(_url);
    }
  })
];
```

## 发布说明

```bash
# 仅发布模块基础功能
npm run pub-old
# 发布模块基础功能+文档站点，since@1.2.7版本及其之后的版本，均采用该模式进行发布
npm run pub
# 采用examplecjs进行打包文档模块，会生成单一js
npm run examplecjs
```

## 精选组件说明

### 视频播放、点播

* [西瓜播放器](http://h5player.bytedance.com/)、[源码](https://github.com/bytedance/xgplayer)（主推，字节跳动开源，集播放点播于一体、插件多，非常适合多场景应用）
* [videojs](https://docs.videojs.com/tutorial-react.html) （视频功能较强，使用范围交广，也是西瓜视频的早期替代方案，项目中可以使用）
* [video-react](https://github.com/video-react/video-react)、[react-player](https://github.com/CookPete/react-player) （react 组件 video，不推荐使用）

### 拖拽

* [react-draggable](https://github.com/mzabriskie/react-draggable) （主推，内部UI库中，多处拖拽场景，均有使用到，也针对该库做了相关扩展）
* [react-dnd](https://github.com/react-dnd/react-dnd) （比较好的拖拽库，使用范围广）

### 其它

* [react-virtualized](https://github.com/bvaughn/react-virtualized) 长列表滚动，有相应场景，可以使用该组件
* 自定义打包 docsite,

```js
// 简单使用
// index.js
import React from 'react';
import { render } from 'react-dom';
import { Router, hashHistory } from 'amos-react-router';
import { AFRouter } from 'amos-framework/docsite/entry';

// 复制 amos-doc 中的样式
import './../styles';

const App = (props) => <div>{props.children}</div>;

function handleEnter(nextState, replace, callback){
  const pathname = nextState.location.pathname;
  if (pathname === '/'){
    replace('/framework');
  }
  callback();
}

render(
  <Router history={hashHistory}>
    <Router path="/" component={App} onEnter={handleEnter}>
      {AFRouter}
    </Router>
  </Router>,
  document.getElementById('app')
);

// 不使用路由, 自行安装 `ray-page-container`
// index2.js
import React from 'react';
import { render } from 'react-dom';
import DocSite from 'amos-framework/docsite/entry2';

import 'amos-framework/dist/amosframework.css';

render(<DocSite />, document.getElementById('app'));

// webpack.config.js
const docitConfig = require('amos-build/lib/docitConfig');
const __ENV__ = require('amos-build/lib/tools/__ENV__');

const defaultConfig = docitConfig({
  entry: {
    app: './index.js',
  },
  tpl: './tpl.html',
  toFile: 'index.html',
  port: 5000,
  lint: false,
  sourceMap: __ENV__ === 'production' ? false : true
});

// mdx
defaultConfig.module.rules.push(
  { test: /\.mdx$/, loader: 'file-rawtxt-loader' }
);

module.exports = defaultConfig;
```

### 常用说明

#### 监听页面退出

```js
import React, { Component } from 'react';
import { withRouter } from 'amos-react-router';

@withRouter
class ContainerDemo extends Component {
  componentDidMount() {
    const { router, route } = this.props;
    router.setRouteLeaveHook(route, this.routerWillLeave);

    // window.onbeforeunload = function(event) {
    //   return window.confirm('确定退出吗');
    // };

    window.addEventListener('beforeunload', this._onbeforeunload, true);
  }

  componentWillUnmount() {
    window.removeEventListener('beforeunload', this._onbeforeunload, true);
  }

  /**
   * 当窗口即将被卸载（关闭）时,会触发该事件.
   * @param {*} evt
   * @returns
   * @see https://developer.mozilla.org/zh-CN/docs/Web/API/WindowEventHandlers/onbeforeunload
   */
  _onbeforeunload = (evt) => {
    const confirmInfo = '确定退出吗';

    const e = evt || window.event;
    if (e){
      e.returnValue = confirmInfo;  // Gecko + IE, 兼容IE8和Firefox 4之前的版本
    }
    // Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
    return confirmInfo;
  }

  routerWillLeave = nextLocation => {
    let flag = window.confirm('要离开此页面吗？\n\n 系统可能不会保存您所做的更改。');
    if (flag) {
      return true;
    }
    return false;
  };

  render() {
    return <div />;
  }
}
```

## major change

### 2021-04-29 v1.7.0

  采用 css 变量处理通用样式，root 节点下存放全局变量，各自组件根节点存放自身变量

### 2019-9-18 v1.2.0

  重大版本迭代，将基础组件的通用样式单位 `rem` 改为 `em`。同时，添加组件样式初始化 mixin。

  why? 部分响应式场景中，会将 `html` 节点的 `font-size` 设置为 `100px、625%` 等值，将会影响基础组件的样式计算。

### 2018-3-28

  添加组件案例
