amis/examples/embed.tsx

209 lines
7.5 KiB
TypeScript

import './polyfills/index';
import React from 'react';
import { render as renderReact } from 'react-dom';
import axios from 'axios';
import copy from 'copy-to-clipboard';
import qs from 'qs';
import {
toast,
alert,
confirm,
ToastComponent,
AlertComponent,
render as renderAmis
} from '../src/index';
export function embed(container: string | HTMLElement, schema: any, data: any, env: any) {
if (typeof container === 'string') {
container = document.querySelector(container) as HTMLElement;
}
if (!container) {
console.error('选择器不对,页面上没有此元素');
return;
} else if (container.tagName === 'BODY') {
let div = document.createElement('div');
container.appendChild(div);
container = div;
}
container.classList.add('amis-scope');
let scoped:any;
const normalizeLink = (to:string) => {
to = to || '';
const location = window.location;
if (to && to[0] === '#') {
to = location.pathname + location.search + to;
} else if (to && to[0] === '?') {
to = location.pathname + to;
}
const idx = to.indexOf('?');
const idx2 = to.indexOf('#');
let pathname = ~idx ? to.substring(0, idx) : ~idx2 ? to.substring(0, idx2) : to;
let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
let hash = ~idx2 ? to.substring(idx2) : '';
if (!pathname) {
pathname = location.pathname;
} else if (pathname[0] != '/' && !/^https?\:\/\//.test(pathname)) {
let relativeBase = location.pathname;
const paths = relativeBase.split('/');
paths.pop();
let m;
while ((m = /^\.\.?\//.exec(pathname))) {
if (m[0] === '../') {
paths.pop();
}
pathname = pathname.substring(m[0].length);
}
pathname = paths.concat(pathname).join('/');
}
return pathname + search + hash;
}
const responseAdpater = (api:any) => (value:any) => {
let response = value.data;
if (env && env.responseAdpater) {
const url = api.url;
const idx = api.url.indexOf('?');
const query = ~idx ? qs.parse(api.url.substring(idx)) : {};
const request = {
...api,
query: query,
body: api.data
};
response = env.responseAdpater(api, response, query, request);
} else {
if (response.hasOwnProperty('errno')) {
response.status = response.errno;
response.msg = response.errmsg;
} else if (response.hasOwnProperty('no')) {
response.status = response.no;
response.msg = response.error;
}
}
const result = {
...value,
data: response
}
return result;
};
renderReact((
<div className="amis-routes-wrapper">
<ToastComponent position={env && env.toastPosition || 'top-right'} closeButton={false} timeOut={5000} extendedTimeOut={3000}/>
<AlertComponent container={container} />
{renderAmis(schema, {
...data,
scopeRef: (ref:any) => scoped = ref
}, {
getModalContainer: () => document.querySelector('.amis-scope'),
notify: (type: string, msg: string) => toast[type] ? toast[type](msg, type === 'error' ? '系统错误' : '系统消息') : console.warn('[Notify]', type, msg),
alert,
confirm,
updateLocation: (to:any, replace:boolean) => {
if (to === 'goBack') {
return window.history.back();
}
replace || (location.href = normalizeLink(to));
},
isCurrentUrl: (to:string) => {
const link = normalizeLink(to);
const location = window.location;
let pathname = link;
let search = '';
const idx = link.indexOf('?');
if (~idx) {
pathname = link.substring(0, idx);
search = link.substring(idx);
}
if (search) {
if (pathname !== location.pathname || !location.search) {
return false;
}
const query = qs.parse(search.substring(1));
const currentQuery = qs.parse(location.search.substring(1));
return Object.keys(query).every(key => query[key] === currentQuery[key]);
} else if (pathname === location.pathname) {
return true;
}
return false;
},
jumpTo: (to:string, action?:any) => {
if (to === 'goBack') {
return window.history.back();
}
to = normalizeLink(to);
if (action && action.actionType === 'url') {
action.blank === false ? (window.location.href = to) : window.open(to);
return;
}
if (/^https?:\/\//.test(to)) {
window.location.replace(to);
} else {
location.href = to;
}
},
fetcher: (api: any) => {
let {
url,
method,
data,
responseType,
config,
headers
} = api;
config = config || {};
config.withCredentials = true;
responseType && (config.responseType = responseType);
if (config.cancelExecutor) {
config.cancelToken = new (axios as any).CancelToken(config.cancelExecutor);
}
config.headers = headers || {};
config.method = method;
if (method === 'get' && data) {
config.params = data;
} else if (data && data instanceof FormData) {
// config.headers['Content-Type'] = 'multipart/form-data';
} else if (data
&& typeof data !== 'string'
&& !(data instanceof Blob)
&& !(data instanceof ArrayBuffer)
) {
data = JSON.stringify(data);
config.headers['Content-Type'] = 'application/json';
}
data && (config.data = data);
return axios(url, config)
.then(responseAdpater(api));
},
isCancel: (value: any) => (axios as any).isCancel(value),
copy: (contents: string, options: any = {}) => {
const ret = copy(contents, options);
ret && options.shutup !== true && toast.info('内容已拷贝到剪切板');
return ret;
},
richTextToken: '',
...env
})}
</div>
), container);
return scoped;
}