feat: copy 支持富文本 (#2695)

This commit is contained in:
吴多益 2021-10-13 11:41:43 +08:00 committed by GitHub
parent 303c5a3a62
commit 6dca72d875
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 88 additions and 68 deletions

View File

@ -555,6 +555,18 @@ icon 也可以是 url 地址,比如
} }
``` ```
可以通过 `copyFormat` 设置复制的格式,默认是文本
```schema: scope="body"
{
"label": "复制一段富文本",
"type": "button",
"actionType": "copy",
"copyFormat": "text/html",
"content": "<a href='http://www.baidu.com'>link</a> <b>bold</b>"
}
```
**属性表** **属性表**
| 属性名 | 类型 | 默认值 | 说明 | | 属性名 | 类型 | 默认值 | 说明 |

View File

@ -664,10 +664,10 @@ class MyComponent extends React.Component<any, any> {
##### copy ##### copy
```ts ```ts
(contents: string, options?: {shutup: boolean}) (contents: string, options?: {silent: boolean, format?: string})
``` ```
用来实现内容复制 用来实现内容复制,其中 `format` 可以为 text/html或 text/plain
##### session ##### session

View File

@ -190,8 +190,8 @@ export default class PlayGround extends React.Component {
toast[type] ? toast[type](msg) : console.warn('[Notify]', type, msg), toast[type] ? toast[type](msg) : console.warn('[Notify]', type, msg),
alert, alert,
confirm, confirm,
copy: content => { copy: (content, options) => {
copy(content); copy(content, options);
toast.success(__('System.copy')); toast.success(__('System.copy'));
} }
}; };

View File

@ -116,8 +116,8 @@ export default function (schema, showCode, envOverrides) {
return axios[method](url, data, config); return axios[method](url, data, config);
}, },
isCancel: value => axios.isCancel(value), isCancel: value => axios.isCancel(value),
copy: content => { copy: (content, options) => {
copy(content); copy(content, options);
toast.success('内容已复制到粘贴板'); toast.success('内容已复制到粘贴板');
}, },
blockRouting: fn => { blockRouting: fn => {

View File

@ -176,7 +176,7 @@ export function embed(
const amisEnv = { const amisEnv = {
getModalContainer: () => getModalContainer: () =>
env?.getModalContainer?.() || document.querySelector('.amis-scope'), env?.getModalContainer?.() || document.querySelector('.amis-scope'),
notify: (type: string, msg: string) => notify: (type: 'success' | 'error' | 'warning' | 'info', msg: string) =>
toast[type] ? toast[type](msg) : console.warn('[Notify]', type, msg), toast[type] ? toast[type](msg) : console.warn('[Notify]', type, msg),
alert, alert,
confirm, confirm,
@ -283,7 +283,7 @@ export function embed(
} }
// 支持返回各种报错信息 // 支持返回各种报错信息
config.validateStatus = function (status) { config.validateStatus = function () {
return true; return true;
}; };
@ -320,8 +320,8 @@ export function embed(
}, },
isCancel: (value: any) => (axios as any).isCancel(value), isCancel: (value: any) => (axios as any).isCancel(value),
copy: (contents: string, options: any = {}) => { copy: (contents: string, options: any = {}) => {
const ret = copy(contents, options); const ret = copy(contents);
ret && options.shutup !== true && toast.info(__('System.copy')); ret && options.silent !== true && toast.info(__('System.copy'));
return ret; return ret;
}, },
richTextToken: '', richTextToken: '',

View File

@ -39,7 +39,7 @@ class AMISComponent extends React.Component {
responseType, responseType,
config, // config, //
headers // headers //
}: any) => { }) => {
config = { config = {
dataType: 'json', dataType: 'json',
...config ...config
@ -52,7 +52,7 @@ class AMISComponent extends React.Component {
} }
// //
config.validateStatus = function (status) { config.validateStatus = function () {
return true; return true;
}; };
@ -77,9 +77,9 @@ class AMISComponent extends React.Component {
} }
return response; return response;
}, },
isCancel: (value: any) => (axios as any).isCancel(value), isCancel: value => axios.isCancel(value),
copy: content => { copy: (content, optinos) => {
copy(content); copy(content, optinos);
toast.success('内容已复制到粘贴板'); toast.success('内容已复制到粘贴板');
} }
})} })}
@ -88,6 +88,6 @@ class AMISComponent extends React.Component {
} }
} }
export function bootstrap(mountTo, initalState) { export function bootstrap(mountTo) {
render(<AMISComponent />, mountTo); render(<AMISComponent />, mountTo);
} }

View File

@ -116,12 +116,14 @@ export class RootRenderer extends React.Component<RootRendererProps> {
); );
} else if (action.actionType === 'email') { } else if (action.actionType === 'email') {
const mailTo = filter(action.to, ctx); const mailTo = filter(action.to, ctx);
const mailInfo = mapValues(pick(action, 'to', 'cc', 'bcc', 'subject', 'body'), val => filter(val, ctx)); const mailInfo = mapValues(
pick(action, 'to', 'cc', 'bcc', 'subject', 'body'),
val => filter(val, ctx)
);
const mailStr = qs.stringify(mailInfo); const mailStr = qs.stringify(mailInfo);
const mailto = `mailto:${mailTo}?${mailStr}`; const mailto = `mailto:${mailTo}?${mailStr}`;
window.open(mailto); window.open(mailto);
} else if (action.actionType === 'dialog') { } else if (action.actionType === 'dialog') {
store.setCurrentAction(action); store.setCurrentAction(action);
store.openDialog(ctx); store.openDialog(ctx);
@ -159,7 +161,10 @@ export class RootRenderer extends React.Component<RootRendererProps> {
action.actionType === 'copy' && action.actionType === 'copy' &&
(action.content || action.copy) (action.content || action.copy)
) { ) {
env.copy && env.copy(filter(action.content || action.copy, ctx, '| raw')); env.copy &&
env.copy(filter(action.content || action.copy, ctx, '| raw'), {
format: action.copyFormat
});
} }
} }

View File

@ -41,7 +41,7 @@ export interface RendererEnv {
schema: Schema, schema: Schema,
props: any props: any
) => null | RendererConfig; ) => null | RendererConfig;
copy?: (contents: string) => void; copy?: (contents: string, format?: any) => void;
getModalContainer?: () => HTMLElement; getModalContainer?: () => HTMLElement;
theme: ThemeInstance; theme: ThemeInstance;
affixOffsetTop: number; affixOffsetTop: number;

View File

@ -99,7 +99,7 @@ export interface RenderOptions {
schema: Schema, schema: Schema,
props: any props: any
) => null | RendererConfig; ) => null | RendererConfig;
copy?: (contents: string) => void; copy?: (contents: string, options?: any) => void;
getModalContainer?: () => HTMLElement; getModalContainer?: () => HTMLElement;
loadRenderer?: ( loadRenderer?: (
schema: Schema, schema: Schema,

View File

@ -347,6 +347,7 @@ const ActionProps = [
'mergeData', 'mergeData',
'index', 'index',
'copy', 'copy',
'copyFormat',
'payload', 'payload',
'requireSelected' 'requireSelected'
]; ];

View File

@ -32,54 +32,56 @@ export interface CopyableProps extends RendererProps {
copyable: SchemaCopyable; copyable: SchemaCopyable;
} }
export const HocCopyable = () => (Component: React.ComponentType<any>): any => { export const HocCopyable =
class QuickEditComponent extends React.PureComponent<CopyableProps, any> { () =>
static ComposedComponent = Component; (Component: React.ComponentType<any>): any => {
handleClick(content: string) { class QuickEditComponent extends React.PureComponent<CopyableProps, any> {
const {env} = this.props; static ComposedComponent = Component;
env.copy && env.copy(content); handleClick(content: string) {
} const {env, copyFormat} = this.props;
render() { env.copy && env.copy(content, {format: copyFormat});
const { }
copyable, render() {
name, const {
className, copyable,
data, name,
noHoc, className,
classnames: cx, data,
translate: __ noHoc,
} = this.props; classnames: cx,
translate: __
if (copyable && !noHoc) { } = this.props;
const content = filter(
(copyable as SchemaCopyableObject).content || if (copyable && !noHoc) {
'${' + name + ' | raw }', const content = filter(
data (copyable as SchemaCopyableObject).content ||
); '${' + name + ' | raw }',
if (content) { data
return ( );
<Component if (content) {
{...this.props} return (
className={cx(`Field--copyable`, className)} <Component
> {...this.props}
<Component {...this.props} wrapperComponent={''} noHoc /> className={cx(`Field--copyable`, className)}
<a >
key="edit-btn" <Component {...this.props} wrapperComponent={''} noHoc />
data-tooltip={__('Copyable.tip')} <a
className={cx('Field-copyBtn')} key="edit-btn"
onClick={this.handleClick.bind(this, content)} data-tooltip={__('Copyable.tip')}
> className={cx('Field-copyBtn')}
<Icon icon="copy" className="icon" /> onClick={this.handleClick.bind(this, content)}
</a> >
</Component> <Icon icon="copy" className="icon" />
); </a>
} </Component>
);
}
}
return <Component {...this.props} />;
} }
return <Component {...this.props} />;
} }
} hoistNonReactStatic(QuickEditComponent, Component);
hoistNonReactStatic(QuickEditComponent, Component); return QuickEditComponent;
return QuickEditComponent; };
};
export default HocCopyable; export default HocCopyable;