forked from p96170835/amis
优化关联选择的样式
This commit is contained in:
parent
aa1040d991
commit
1bbee5bdfb
|
@ -8,6 +8,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(1turn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-spin {
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
.#{$ns}Spinner-overlay {
|
.#{$ns}Spinner-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
|
@ -563,7 +563,31 @@
|
||||||
border-right: 1px solid $borderColor;
|
border-right: 1px solid $borderColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-placeholder {
|
&-reload {
|
||||||
@include checkboxes-placeholder();
|
text-align: center;
|
||||||
|
color: $info;
|
||||||
|
margin: 20px 0 0;
|
||||||
|
|
||||||
|
&.is-clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-box {
|
||||||
|
line-height: $Form-input-lineHeight;
|
||||||
|
font-size: $fontSizeSm;
|
||||||
|
color: $text--muted-color;
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
> p {
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px 0 20px;
|
||||||
|
color: $text--muted-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import TreeCheckboxes from './TreeCheckboxes';
|
||||||
import ChainedCheckboxes from './ChainedCheckboxes';
|
import ChainedCheckboxes from './ChainedCheckboxes';
|
||||||
import Spinner from './Spinner';
|
import Spinner from './Spinner';
|
||||||
import TreeRadios from './TreeRadios';
|
import TreeRadios from './TreeRadios';
|
||||||
|
import {Icon} from './icons';
|
||||||
|
|
||||||
export interface AssociatedCheckboxesProps extends CheckboxesProps {
|
export interface AssociatedCheckboxesProps extends CheckboxesProps {
|
||||||
leftOptions: Options;
|
leftOptions: Options;
|
||||||
|
@ -87,6 +88,11 @@ export class AssociatedCheckboxes extends Checkboxes<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleRetry(option: Option) {
|
||||||
|
const {onDeferLoad} = this.props;
|
||||||
|
onDeferLoad?.(option);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
|
@ -132,8 +138,28 @@ export class AssociatedCheckboxes extends Checkboxes<
|
||||||
<div className={cx('AssociatedCheckboxes-right')}>
|
<div className={cx('AssociatedCheckboxes-right')}>
|
||||||
{this.state.leftValue ? (
|
{this.state.leftValue ? (
|
||||||
selectdOption ? (
|
selectdOption ? (
|
||||||
selectdOption.defer && selectdOption.loading ? (
|
selectdOption.defer && !selectdOption.loaded ? (
|
||||||
<Spinner size="sm" show />
|
<div className={cx('AssociatedCheckboxes-box')}>
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
'AssociatedCheckboxes-reload',
|
||||||
|
selectdOption.loading ? 'is-spin' : 'is-clickable'
|
||||||
|
)}
|
||||||
|
onClick={
|
||||||
|
selectdOption.loading
|
||||||
|
? undefined
|
||||||
|
: this.handleRetry.bind(this, selectdOption)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon icon="reload" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{selectdOption.loading ? (
|
||||||
|
<p>加载中</p>
|
||||||
|
) : (
|
||||||
|
<p>点击刷新重新加载</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
) : rightMode === 'table' ? (
|
) : rightMode === 'table' ? (
|
||||||
<TableCheckboxes
|
<TableCheckboxes
|
||||||
columns={columns!}
|
columns={columns!}
|
||||||
|
@ -166,12 +192,12 @@ export class AssociatedCheckboxes extends Checkboxes<
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<div className={cx('AssociatedCheckboxes-placeholder')}>
|
<div className={cx('AssociatedCheckboxes-box')}>
|
||||||
配置错误,选项无法与左侧选项对应
|
配置错误,选项无法与左侧选项对应
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<div className={cx('AssociatedCheckboxes-placeholder')}>
|
<div className={cx('AssociatedCheckboxes-box')}>
|
||||||
请先选择左侧数据
|
请先选择左侧数据
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -66,6 +66,9 @@ import LocationIcon from '../icons/location.svg';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import ComboDraggerIcon from '../icons/combo-dragger.svg';
|
import ComboDraggerIcon from '../icons/combo-dragger.svg';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
import ReloadIcon from '../icons/reload.svg';
|
||||||
|
|
||||||
// 兼容原来的用法,后续不直接试用。
|
// 兼容原来的用法,后续不直接试用。
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export const closeIcon = <CloseIcon />;
|
export const closeIcon = <CloseIcon />;
|
||||||
|
@ -129,6 +132,7 @@ registerIcon('move', MoveIcon);
|
||||||
registerIcon('info', InfoIcon);
|
registerIcon('info', InfoIcon);
|
||||||
registerIcon('location', LocationIcon);
|
registerIcon('location', LocationIcon);
|
||||||
registerIcon('combo-dragger', ComboDraggerIcon);
|
registerIcon('combo-dragger', ComboDraggerIcon);
|
||||||
|
registerIcon('reload', ReloadIcon);
|
||||||
|
|
||||||
export function Icon({
|
export function Icon({
|
||||||
icon,
|
icon,
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" version="1.1">
|
||||||
|
<g fill="currentColor" fill-rule="nonzero">
|
||||||
|
<path d="M8.05031447,14.0555556 C5.93710692,14.0555556 4.02515723,12.9861111 2.91823899,11.2361111 L5.03144654,9.19444444 L0,9.19444444 L0,14.0555556 L1.40880503,12.6944444 C2.91823899,14.7361111 5.33333333,16 8.05031447,16 C12.0754717,16 15.4968553,13.1805556 16,9.29166667 L13.9874214,9 C13.5849057,11.9166667 11.0691824,14.0555556 8.05031447,14.0555556 Z M14.591195,3.30555556 C13.081761,1.26388889 10.6666667,0 7.94968553,0 C3.9245283,0 0.503144654,2.81944444 0,6.70833333 L2.01257862,7 C2.41509434,4.08333333 4.93081761,1.94444444 7.94968553,1.94444444 C10.0628931,1.94444444 11.9748428,3.01388889 13.081761,4.76388889 L10.9685535,6.80555556 L16,6.80555556 L16,1.94444444 L14.591195,3.30555556 Z" id="Shape">
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 902 B |
|
@ -61,7 +61,7 @@ export interface OptionsControlProps extends FormControlProps, OptionProps {
|
||||||
selectedOptions: Array<Option>;
|
selectedOptions: Array<Option>;
|
||||||
setOptions: (value: Array<any>, skipNormalize?: boolean) => void;
|
setOptions: (value: Array<any>, skipNormalize?: boolean) => void;
|
||||||
setLoading: (value: boolean) => void;
|
setLoading: (value: boolean) => void;
|
||||||
reloadOptions: () => void;
|
reloadOptions: (setError?: boolean) => void;
|
||||||
deferLoad: (option: Option) => void;
|
deferLoad: (option: Option) => void;
|
||||||
creatable?: boolean;
|
creatable?: boolean;
|
||||||
onAdd?: (
|
onAdd?: (
|
||||||
|
@ -435,6 +435,11 @@ export function registerOptionsControl(config: OptionsConfig) {
|
||||||
// 当有 action 触发,如果指定了 reload 目标组件,有可能会来到这里面来
|
// 当有 action 触发,如果指定了 reload 目标组件,有可能会来到这里面来
|
||||||
@autobind
|
@autobind
|
||||||
reload() {
|
reload() {
|
||||||
|
this.reloadOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
reloadOptions(setError?: boolean) {
|
||||||
const {source, formItem, data, onChange} = this.props;
|
const {source, formItem, data, onChange} = this.props;
|
||||||
|
|
||||||
if (formItem && isPureVariable(source as string)) {
|
if (formItem && isPureVariable(source as string)) {
|
||||||
|
@ -448,7 +453,14 @@ export function registerOptionsControl(config: OptionsConfig) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return formItem.loadOptions(source, data, undefined, false, onChange);
|
return formItem.loadOptions(
|
||||||
|
source,
|
||||||
|
data,
|
||||||
|
undefined,
|
||||||
|
false,
|
||||||
|
onChange,
|
||||||
|
setError
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
|
|
|
@ -354,11 +354,13 @@ export const FormItemStore = types
|
||||||
const fetchOptions: (
|
const fetchOptions: (
|
||||||
api: Api,
|
api: Api,
|
||||||
data?: object,
|
data?: object,
|
||||||
config?: fetchOptions
|
config?: fetchOptions,
|
||||||
|
setErrorFlag?: boolean
|
||||||
) => Promise<Payload | null> = flow(function* getInitData(
|
) => Promise<Payload | null> = flow(function* getInitData(
|
||||||
api: string,
|
api: string,
|
||||||
data: object,
|
data: object,
|
||||||
config?: fetchOptions
|
config?: fetchOptions,
|
||||||
|
setErrorFlag?: boolean
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (loadCancel) {
|
if (loadCancel) {
|
||||||
|
@ -382,8 +384,11 @@ export const FormItemStore = types
|
||||||
let result: any = null;
|
let result: any = null;
|
||||||
|
|
||||||
if (!json.ok) {
|
if (!json.ok) {
|
||||||
|
setErrorFlag !== false &&
|
||||||
setError(
|
setError(
|
||||||
`加载选项失败,原因:${json.msg || (config && config.errorMessage)}`
|
`加载选项失败,原因:${
|
||||||
|
json.msg || (config && config.errorMessage)
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
(getRoot(self) as IRendererStore).notify(
|
(getRoot(self) as IRendererStore).notify(
|
||||||
'error',
|
'error',
|
||||||
|
@ -426,7 +431,8 @@ export const FormItemStore = types
|
||||||
data?: object,
|
data?: object,
|
||||||
config?: fetchOptions,
|
config?: fetchOptions,
|
||||||
clearValue?: boolean,
|
clearValue?: boolean,
|
||||||
onChange?: (value: any) => void
|
onChange?: (value: any) => void,
|
||||||
|
setErrorFlag?: boolean
|
||||||
) => Promise<Payload | null> = flow(function* getInitData(
|
) => Promise<Payload | null> = flow(function* getInitData(
|
||||||
api: string,
|
api: string,
|
||||||
data: object,
|
data: object,
|
||||||
|
@ -436,9 +442,10 @@ export const FormItemStore = types
|
||||||
value: any,
|
value: any,
|
||||||
submitOnChange: boolean,
|
submitOnChange: boolean,
|
||||||
changeImmediately: boolean
|
changeImmediately: boolean
|
||||||
) => void
|
) => void,
|
||||||
|
setErrorFlag?: boolean
|
||||||
) {
|
) {
|
||||||
let json = yield fetchOptions(api, data, config);
|
let json = yield fetchOptions(api, data, config, setErrorFlag);
|
||||||
if (!json) {
|
if (!json) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -490,8 +497,15 @@ export const FormItemStore = types
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let json = yield fetchOptions(api, data, config);
|
let json = yield fetchOptions(api, data, config, false);
|
||||||
if (!json) {
|
if (!json) {
|
||||||
|
setOptions(
|
||||||
|
spliceTree(self.options, indexes, 1, {
|
||||||
|
...option,
|
||||||
|
loading: false,
|
||||||
|
error: true
|
||||||
|
})
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue