mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
添加用户选择结果展示组件
This commit is contained in:
parent
080dbe33a7
commit
25075b2298
@ -809,7 +809,7 @@ export default {
|
||||
label: false,
|
||||
value: 'none',
|
||||
// mode: 'inline',
|
||||
columnClassName: 'v-middle w-sm no-grow',
|
||||
columnClassName: 'v-middle w-ssm no-grow',
|
||||
options: [
|
||||
{
|
||||
label: '不重复',
|
||||
|
@ -1147,6 +1147,10 @@
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.w-ssm {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.w-sm {
|
||||
width: 150px;
|
||||
}
|
||||
@ -1155,6 +1159,10 @@
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.h-ssm {
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.w {
|
||||
width: 200px;
|
||||
}
|
||||
|
72
scss/components/form/_selections.scss
Normal file
72
scss/components/form/_selections.scss
Normal file
@ -0,0 +1,72 @@
|
||||
.#{$ns}Selections {
|
||||
height: 100%;
|
||||
min-width: px2rem(200px);
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&-title {
|
||||
height: $Form-input-height;
|
||||
background: $Table-thead-bg;
|
||||
font-size: $Form-input-fontSize;
|
||||
padding: (
|
||||
$Form-input-height - $Form-input-lineHeight * $Form-input-fontSize
|
||||
)/2 $gap-sm;
|
||||
}
|
||||
|
||||
&-placeholder {
|
||||
color: $Form-input-placeholderColor;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
flex-basis: $Form-input-height;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&-items {
|
||||
flex-grow: 1;
|
||||
height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: $Form-input-height;
|
||||
line-height: $Form-input-lineHeight;
|
||||
font-size: $Form-input-fontSize;
|
||||
padding: (
|
||||
$Form-input-height - $Form-input-lineHeight * $Form-input-fontSize
|
||||
)/2 $gap-sm;
|
||||
|
||||
> label {
|
||||
flex-basis: px2rem(50px);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
> .#{$ns}Selections-dragbar {
|
||||
width: px2rem(20px);
|
||||
position: relative;
|
||||
left: px2rem(-5px);
|
||||
color: $icon-color;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
&--dragging {
|
||||
> * {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-delBtn {
|
||||
color: $icon-color;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $icon-onHover-color;
|
||||
}
|
||||
}
|
||||
}
|
@ -550,6 +550,7 @@ $Combo--horizontal-dragger-top: px2rem(5px);
|
||||
@import '../components/form/switch';
|
||||
@import '../components/form/number';
|
||||
@import '../components/form/select';
|
||||
@import '../components/form/selections';
|
||||
@import '../components/form/list';
|
||||
@import '../components/form/location';
|
||||
@import '../components/form/matrix';
|
||||
|
@ -213,6 +213,7 @@ pre {
|
||||
@import '../components/form/switch';
|
||||
@import '../components/form/number';
|
||||
@import '../components/form/select';
|
||||
@import '../components/form/selections';
|
||||
@import '../components/form/list';
|
||||
@import '../components/form/location';
|
||||
@import '../components/form/matrix';
|
||||
|
@ -78,6 +78,7 @@ $Form-input-borderColor: #cfdadd;
|
||||
@import '../components/form/switch';
|
||||
@import '../components/form/number';
|
||||
@import '../components/form/select';
|
||||
@import '../components/form/selections';
|
||||
@import '../components/form/list';
|
||||
@import '../components/form/location';
|
||||
@import '../components/form/matrix';
|
||||
|
159
src/components/Selections.tsx
Normal file
159
src/components/Selections.tsx
Normal file
@ -0,0 +1,159 @@
|
||||
/**
|
||||
* 用来显示选择结果,垂直显示。支持移出、排序等操作。
|
||||
*/
|
||||
import React from 'react';
|
||||
import {Option} from './Select';
|
||||
import {ThemeProps, themeable} from '../theme';
|
||||
import {Icon} from './icons';
|
||||
import {autobind, guid} from '../utils/helper';
|
||||
import Sortable from 'sortablejs';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
|
||||
export interface SelectionsProps extends ThemeProps {
|
||||
className?: string;
|
||||
value?: Array<Option>;
|
||||
onChange?: (value: Array<Option>) => void;
|
||||
sortable?: boolean;
|
||||
disabled?: boolean;
|
||||
title?: string;
|
||||
placeholder: string;
|
||||
optionRender: (option: Option) => JSX.Element;
|
||||
itemClassName?: string;
|
||||
}
|
||||
|
||||
export class Selections extends React.Component<SelectionsProps> {
|
||||
static defaultProps: Pick<SelectionsProps, 'placeholder' | 'optionRender'> = {
|
||||
placeholder: '请先选择数据',
|
||||
optionRender: (option: Option) => <span>{option.label}</span>
|
||||
};
|
||||
|
||||
id = guid();
|
||||
sortable?: Sortable;
|
||||
|
||||
componentDidMount() {
|
||||
this.props.sortable && this.initSortable();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.props.sortable) {
|
||||
this.sortable || this.initSortable();
|
||||
} else {
|
||||
this.desposeSortable();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.desposeSortable();
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleRemove(e: React.MouseEvent<HTMLElement>) {
|
||||
const index = parseInt(e.currentTarget.getAttribute('data-index')!, 10);
|
||||
const {value, onChange} = this.props;
|
||||
|
||||
if (!Array.isArray(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newValue = value.concat();
|
||||
newValue.splice(index, 1);
|
||||
onChange?.(newValue);
|
||||
}
|
||||
|
||||
initSortable() {
|
||||
const ns = this.props.classPrefix;
|
||||
const dom = findDOMNode(this) as HTMLElement;
|
||||
const container = dom.querySelector(`.${ns}Selections-items`) as HTMLElement;
|
||||
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.sortable = new Sortable(
|
||||
container,
|
||||
{
|
||||
group: `selections-${this.id}`,
|
||||
animation: 150,
|
||||
handle: `.${ns}Selections-dragbar`,
|
||||
ghostClass: `${ns}Selections-item--dragging`,
|
||||
onEnd: (e: any) => {
|
||||
// 没有移动
|
||||
if (e.newIndex === e.oldIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 换回来
|
||||
const parent = e.to as HTMLElement;
|
||||
if (e.newIndex < e.oldIndex && e.oldIndex < parent.childNodes.length - 1) {
|
||||
parent.insertBefore(e.item, parent.childNodes[e.oldIndex + 1]);
|
||||
} else if (e.oldIndex < parent.childNodes.length - 1) {
|
||||
parent.insertBefore(e.item, parent.childNodes[e.oldIndex]);
|
||||
} else {
|
||||
parent.appendChild(e.item);
|
||||
}
|
||||
|
||||
const value = this.props.value;
|
||||
if (!Array.isArray(value)) {
|
||||
return;
|
||||
}
|
||||
const newValue = value.concat();
|
||||
newValue.splice(e.newIndex, 0, newValue.splice(e.oldIndex, 1)[0]);
|
||||
this.props.onChange?.(newValue);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
desposeSortable() {
|
||||
this.sortable?.destroy();
|
||||
delete this.sortable;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
classnames: cx,
|
||||
className,
|
||||
value,
|
||||
placeholder,
|
||||
optionRender,
|
||||
disabled,
|
||||
title,
|
||||
itemClassName,
|
||||
sortable
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx('Selections', className)}>
|
||||
{title ? <div className={cx('Selections-title')}>{title}</div> : null}
|
||||
|
||||
{Array.isArray(value) && value.length ? (
|
||||
<div className={cx('Selections-items')}>
|
||||
{value.map((option, index) => (
|
||||
<div className={cx('Selections-item', itemClassName, option?.className)} key={index}>
|
||||
{sortable && !disabled ? (
|
||||
<Icon className={cx('Selections-dragbar')} icon="combo-dragger"/>
|
||||
) : null}
|
||||
|
||||
<label>{optionRender(option)}</label>
|
||||
|
||||
{!disabled ? (
|
||||
<a
|
||||
className={cx('Selections-delBtn')}
|
||||
data-index={index}
|
||||
onClick={this.handleRemove}
|
||||
>
|
||||
<Icon icon="close" />
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className={cx('Selections-placeholder')}>{placeholder}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Selections);
|
Loading…
Reference in New Issue
Block a user