feat:图片上传支持配置占位图样式及其比例等 (#1665)

* feat:图片上传支持配置占位图样式及其比例等

* fix conflict

* 更新snapshot

* feat:表格中图片上传支持默认图片

* 增加fixedSize配置项支持用户自定义图片框尺寸

* 拆分fixedSize配置项

* 删除无用代码

Co-authored-by: 邓黔川 <dengqianchuan@baidu.com>
Co-authored-by: dqc <qianchuan.deng@gmail.com>
This commit is contained in:
qianchuan 2021-03-18 12:00:26 +08:00 committed by GitHub
parent 9084267867
commit 8bdc387bd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 181 additions and 79 deletions

View File

@ -1542,6 +1542,12 @@ exports[`Renderer:Wizard initApi reload 3`] = `
<div
class="a-Page-body"
>
<div
class="a-Spinner-overlay"
/>
<div
class="a-Spinner a-Spinner--overlay a-Spinner--lg"
/>
<div
class="a-Panel a-Panel--default a-Wizard a-Wizard--horizontal"
style="position: relative;"

View File

@ -160,25 +160,28 @@ order: 27
除了支持 [普通表单项属性表](./formitem#%E5%B1%9E%E6%80%A7%E8%A1%A8) 中的配置以外,还支持下面一些配置
| 属性名 | 类型 | 默认值 | 说明 |
| ---------------- | ------------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------- |
| receiver | [API](../../../docs/types/api) | | 上传文件接口 |
| accept | `string` | `.jpeg,.jpg,.png,.gif` | 支持的图片类型格式,请配置此属性为图片后缀,例如`.jpg,.png` |
| maxSize | `number` | | 默认没有限制,当设置后,文件大小大于此值将不允许上传。单位为`B` |
| maxLength | `number` | | 默认没有限制,当设置后,一次只允许上传指定数量文件。 |
| multiple | `boolean` | `false` | 是否多选。 |
| joinValues | `boolean` | `true` | [拼接值](./options#%E6%8B%BC%E6%8E%A5%E5%80%BC-joinvalues) |
| extractValue | `boolean` | `false` | [提取值](./options#%E6%8F%90%E5%8F%96%E5%A4%9A%E9%80%89%E5%80%BC-extractvalue) |
| delimeter | `string` | `,` | [拼接符](./options#%E6%8B%BC%E6%8E%A5%E7%AC%A6-delimiter) |
| autoUpload | `boolean` | `true` | 否选择完就自动开始上传 |
| hideUploadButton | `boolean` | `false` | 隐藏上传按钮 |
| fileField | `string` | `file` | 如果你不想自己存储,则可以忽略此属性。 |
| crop | `boolean`或`{"aspectRatio":""}` | | 用来设置是否支持裁剪。 |
| crop.aspectRatio | `number` | | 裁剪比例。浮点型,默认 `1``1:1`,如果要设置 `16:9` 请设置 `1.7777777777777777``16 / 9`。。 |
| crop.rotatable | `boolean` | `false` | 裁剪时是否可旋转 |
| crop.scalable | `boolean` | `false` | 裁剪时是否可缩放 |
| crop.viewMode | `number` | `1` | 裁剪时的查看模式0 是无限制 |
| limit | Limit | | 限制图片大小,超出不让上传。 |
| 属性名 | 类型 | 默认值 | 说明 |
| ------------------ | ------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| receiver | [API](../../../docs/types/api) | | 上传文件接口 |
| accept | `string` | `.jpeg,.jpg,.png,.gif` | 支持的图片类型格式,请配置此属性为图片后缀,例如`.jpg,.png` |
| maxSize | `number` | | 默认没有限制,当设置后,文件大小大于此值将不允许上传。单位为`B` |
| maxLength | `number` | | 默认没有限制,当设置后,一次只允许上传指定数量文件。 |
| multiple | `boolean` | `false` | 是否多选。 |
| joinValues | `boolean` | `true` | [拼接值](./options#%E6%8B%BC%E6%8E%A5%E5%80%BC-joinvalues) |
| extractValue | `boolean` | `false` | [提取值](./options#%E6%8F%90%E5%8F%96%E5%A4%9A%E9%80%89%E5%80%BC-extractvalue) |
| delimeter | `string` | `,` | [拼接符](./options#%E6%8B%BC%E6%8E%A5%E7%AC%A6-delimiter) |
| autoUpload | `boolean` | `true` | 否选择完就自动开始上传 |
| hideUploadButton | `boolean` | `false` | 隐藏上传按钮 |
| fileField | `string` | `file` | 如果你不想自己存储,则可以忽略此属性。 |
| crop | `boolean`或`{"aspectRatio":""}` | | 用来设置是否支持裁剪。 |
| crop.aspectRatio | `number` | | 裁剪比例。浮点型,默认 `1``1:1`,如果要设置 `16:9` 请设置 `1.7777777777777777``16 / 9`。。 |
| crop.rotatable | `boolean` | `false` | 裁剪时是否可旋转 |
| crop.scalable | `boolean` | `false` | 裁剪时是否可缩放 |
| crop.viewMode | `number` | `1` | 裁剪时的查看模式0 是无限制 |
| limit | Limit | | 限制图片大小,超出不让上传。 |
| defaultImage | `string` | | 默认占位图地址 |
| fixedSize | `boolean` | | 是否开启固定尺寸 |
| fixedSizeClassName | `string` | | 开启固定尺寸时,根据此值控制展示尺寸。例如`h-30`,即图片框高为 h-30,最终上传图片根据此尺寸对应缩放。也可同时设置设置宽度的类名,例如`h-30 w-52`,若不设置宽度类名,则根据父元素尺寸自适应 |
### Limit 属性表

View File

@ -788,6 +788,20 @@ export default {
{
type: 'divider'
},
{
type: 'image',
name: 'image',
inputClassName: 'w-52',
label: '图片有默认占位图',
defaultImage:
'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg',
fixedSize: true,
fixedSizeClassName: 'h-32',
thumbMode: 'contain'
},
{
type: 'divider'
},
{
type: 'image',
name: 'imageCrop',

View File

@ -39,6 +39,22 @@
height: px2rem(108px * 9 / 16);
}
&-thumb--fixed-size {
width: 100%;
padding: 0;
height: 100%;
}
&-thumb--fixed-size &-thumb {
width: 100%;
height: 100%;
> img {
width: auto;
height: 100%;
}
}
&-thumb--w-full > img {
width: 100%;
height: auto;

View File

@ -94,8 +94,9 @@
width: px2rem(108px);
height: px2rem(108px);
display: none;
top: px2rem(5px);
left: px2rem(5px);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
justify-content: center;
align-items: center;
@ -253,4 +254,15 @@
line-height: 120px;
text-align: center;
}
&-fixed-size {
width: 100%;
height: 100%;
padding: 0;
}
&-fixed-size &-itemOverlay {
width: 100%;
height: 100%;
}
}

View File

@ -23,6 +23,7 @@ import {
SchemaTokenizeableString,
SchemaUrlPath
} from '../../Schema';
import {filter} from '../../utils/tpl';
/**
* Image
@ -222,6 +223,21 @@ export interface ImageControlSchema extends FormBaseControl {
autoFill?: {
[propName: string]: SchemaTokenizeableString;
};
/**
*
*/
defaultImage?: SchemaUrlPath;
/**
*
*/
fixedSize?: boolean;
/**
* CSS类名
*/
fixedSizeClassName?: SchemaClassName;
}
let preventEvent = (e: any) => e.stopPropagation();
@ -933,7 +949,7 @@ export default class ImageControl extends React.Component<
Math.abs(width / height - limit.aspectRatio) > 0.01
) {
error = __(limit.aspectRatioLabel || 'Image.limitRatio', {
ratio: limit.aspectRatio
ratio: limit.aspectRatio.toFixed(2)
});
}
@ -1095,6 +1111,9 @@ export default class ImageControl extends React.Component<
thumbMode,
thumbRatio,
reCropable,
defaultImage,
fixedSize,
fixedSizeClassName,
translate: __
} = this.props;
@ -1170,12 +1189,17 @@ export default class ImageControl extends React.Component<
? files.map((file, key) => (
<div
key={file.id || key}
className={cx('ImageControl-item', {
'is-uploaded': file.state !== 'uploading',
'is-invalid':
file.state === 'error' ||
file.state === 'invalid'
})}
className={cx(
'ImageControl-item',
{
'is-uploaded': file.state !== 'uploading',
'is-invalid':
file.state === 'error' ||
file.state === 'invalid'
},
fixedSize ? 'ImageControl-fixed-size' : '',
fixedSize ? fixedSizeClassName : ''
)}
>
{file.state === 'invalid' ||
file.state === 'error' ? (
@ -1194,9 +1218,14 @@ export default class ImageControl extends React.Component<
</a>
<a
className={cx('ImageControl-retryBtn', {
'is-disabled': disabled
})}
className={cx(
'ImageControl-retryBtn',
{
'is-disabled': disabled
},
fixedSize ? 'ImageControl-fixed-size' : '',
fixedSize ? fixedSizeClassName : ''
)}
onClick={this.handleRetry.bind(this, key)}
>
<Icon icon="retry" className="icon" />
@ -1221,7 +1250,11 @@ export default class ImageControl extends React.Component<
</a>
<div
key="info"
className={cx('ImageControl-itemInfo')}
className={cx(
'ImageControl-itemInfo',
fixedSize ? 'ImageControl-fixed-size' : '',
fixedSize ? fixedSizeClassName : ''
)}
>
<p>{__('File.uploading')}</p>
<div className={cx('ImageControl-progress')}>
@ -1242,7 +1275,10 @@ export default class ImageControl extends React.Component<
<>
<ImageComponent
key="image"
className={cx('ImageControl-image')}
className={cx(
'ImageControl-image',
fixedSize ? 'Image-thumb--fixed-size' : ''
)}
onLoad={this.handleImageLoaded.bind(
this,
key
@ -1333,14 +1369,29 @@ export default class ImageControl extends React.Component<
{(multiple && (!maxLength || files.length < maxLength)) ||
(!multiple && !files.length) ? (
<label
className={cx('ImageControl-addBtn', {
'is-disabled': disabled
})}
className={cx(
'ImageControl-addBtn',
{
'is-disabled': disabled
},
fixedSize ? 'ImageControl-fixed-size' : '',
fixedSize ? fixedSizeClassName : ''
)}
onClick={this.handleSelect}
data-tooltip={__(placeholder)}
data-position="right"
>
<Icon icon="plus" className="icon" />
{defaultImage ? (
<ImageComponent
key="upload-default-image"
src={filter(defaultImage, this.props.data, '| raw')}
className={cx(
fixedSize ? 'Image-thumb--fixed-size' : ''
)}
/>
) : (
<Icon icon="plus" className="icon" />
)}
{isFocused ? (
<span className={cx('ImageControl-pasteTip')}>