From 749936fdd162872fbba93482c4a6698d0a7e0898 Mon Sep 17 00:00:00 2001 From: Echo Date: Sat, 18 Dec 2021 11:49:27 +0800 Subject: [PATCH 1/9] =?UTF-8?q?fix:=20=E7=A9=BF=E6=A2=AD=E6=A1=86=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/devui-vue/devui/transfer/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/devui-vue/devui/transfer/index.ts b/packages/devui-vue/devui/transfer/index.ts index 2776601564..fb99c5b75d 100644 --- a/packages/devui-vue/devui/transfer/index.ts +++ b/packages/devui-vue/devui/transfer/index.ts @@ -2,7 +2,7 @@ import type { App } from 'vue' import Transfer from './src/transfer' Transfer.install = function (app: App) { - app.component(Transfer.name, Transfer) + app.component(Transfer.name, Transfer) } export { Transfer } @@ -10,7 +10,7 @@ export { Transfer } export default { title: 'Transfer 穿梭框', category: '数据录入', - status: '10%', + status: '40%', install(app: App): void { app.use(Transfer as any) } From 8fb514462693de6dd84db5be19fd526edc794a51 Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 21 Dec 2021 23:12:23 +0800 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=E7=A9=BF=E6=A2=AD=E6=A1=86?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=8B=96=E6=8B=BD=E6=8E=92=E5=BA=8F=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transfer/common/use-transfer-base.ts | 14 +- .../transfer/common/use-transfer-checkbox.ts | 17 +++ .../transfer/common/use-transfer-common.ts | 34 +++++ .../transfer/common/use-transfer-drag.ts | 20 +++ .../devui/transfer/common/use-transfer.ts | 13 +- .../devui/transfer/src/transfer-base.tsx | 99 ++++++++---- .../devui/transfer/src/transfer-checkbox.tsx | 42 +++++ .../devui/transfer/src/transfer-drag-item.tsx | 134 ++++++++++++++++ .../devui/transfer/src/transfer.scss | 48 ++++-- .../devui-vue/devui/transfer/src/transfer.tsx | 18 ++- .../docs/components/transfer/index.md | 143 +++++++++++++++++- 11 files changed, 518 insertions(+), 64 deletions(-) create mode 100644 packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts create mode 100644 packages/devui-vue/devui/transfer/common/use-transfer-common.ts create mode 100644 packages/devui-vue/devui/transfer/common/use-transfer-drag.ts create mode 100644 packages/devui-vue/devui/transfer/src/transfer-checkbox.tsx create mode 100644 packages/devui-vue/devui/transfer/src/transfer-drag-item.tsx diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-base.ts b/packages/devui-vue/devui/transfer/common/use-transfer-base.ts index 4c3b613112..d79f3b5011 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer-base.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer-base.ts @@ -1,10 +1,13 @@ import { computed, ExtractPropTypes, PropType, ComputedRef } from 'vue' import { IItem, TState, TResult } from '../types' import { TransferProps } from './use-transfer' +import { transferCommon, transferDragFunctions } from './use-transfer-common' export type TransferOperationProps = ExtractPropTypes export const transferBaseProps = { + ...transferCommon, + ...transferDragFunctions, sourceOption: { type: Array as () => IItem[], default(): Array { @@ -57,13 +60,13 @@ export const transferBaseProps = { type: Number, default: (): number => 0 }, - showTooltip: { + isSourceDroppable: { type: Boolean, default: (): boolean => false }, - tooltipPosition: { - type: String as PropType<'top' | 'right' | 'bottom' | 'left'>, - default: (): string => 'top' + isTargetDroppable: { + type: Boolean, + default: (): boolean => false }, scopedSlots: { type: Object @@ -76,6 +79,9 @@ export const transferBaseProps = { }, onUpdateCheckeds: { type: Function as PropType<(val: string[]) => void> + }, + onDragend: { + type: Function as unknown as () => ((dragItem: IItem, dropItem: IItem) => void) } } diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts b/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts new file mode 100644 index 0000000000..1f2ec1189b --- /dev/null +++ b/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts @@ -0,0 +1,17 @@ +import { ExtractPropTypes } from '@vue/runtime-core' +import { IItem } from '../types' +import { transferCommon } from './use-transfer-common' + +const transferCheckboxProps = { + ...transferCommon, + data: { + type: Object as () => IItem, + }, + id: { + type: Number + } +} + +export type TransferCheckboxProps = ExtractPropTypes + +export default transferCheckboxProps \ No newline at end of file diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-common.ts b/packages/devui-vue/devui/transfer/common/use-transfer-common.ts new file mode 100644 index 0000000000..6f4e75b295 --- /dev/null +++ b/packages/devui-vue/devui/transfer/common/use-transfer-common.ts @@ -0,0 +1,34 @@ +import { PropType } from '@vue/runtime-core' +import { IItem } from '../types' + +export const transferCommon = { + showTooltip: { + type: Boolean, + default: (): boolean => false + }, + tooltipPosition: { + type: String as PropType<'top' | 'right' | 'bottom' | 'left'>, + default: (): string => 'top' + } +} + +export const transferDragFunctions = { + onDragstart: { + type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) + }, + onDrop: { + type: Function as unknown as () => ((event: Event, dropItem: IItem) => void) + }, + onDragleave: { + type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) + }, + onDragover: { + type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) + }, + onDragenter: { + type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) + }, + onDragend: { + type: Function as unknown as () => ((event: Event, dropItem: IItem) => void) + } +} diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-drag.ts b/packages/devui-vue/devui/transfer/common/use-transfer-drag.ts new file mode 100644 index 0000000000..be1f9f88f6 --- /dev/null +++ b/packages/devui-vue/devui/transfer/common/use-transfer-drag.ts @@ -0,0 +1,20 @@ +import { PropType, ExtractPropTypes } from '@vue/runtime-core' +import { IItem } from '../types' +import { transferCommon, transferDragFunctions } from './use-transfer-common' + +const transferDragProps = { + ...transferCommon, + ...transferDragFunctions, + itemData: { + type: Object as PropType + }, + id: { + type: Number, + default: (): number | null => null + }, + +} + +export type TransferDragProps = ExtractPropTypes + +export default transferDragProps \ No newline at end of file diff --git a/packages/devui-vue/devui/transfer/common/use-transfer.ts b/packages/devui-vue/devui/transfer/common/use-transfer.ts index 414d2dfc5b..566d8546bb 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer.ts @@ -1,7 +1,9 @@ import { ExtractPropTypes, PropType, SetupContext } from 'vue' import { IItem, ITitles, IModel, TState } from '../types' +import { transferCommon } from './use-transfer-common' export const transferProps = { + ...transferCommon, sourceOption: { type: Array as () => IItem[], require: true, @@ -44,14 +46,6 @@ export const transferProps = { type: Boolean, default: (): boolean => false }, - showTooltip: { - type: Boolean, - default: (): boolean => false - }, - tooltipPosition: { - type: String as PropType<'top' | 'right' | 'bottom' | 'left'>, - default: (): string => 'top' - }, beforeTransfer: { type: Function as unknown as () => ((sourceOption: TState, targetOption: TState) => boolean | Promise) }, @@ -72,6 +66,9 @@ export const transferProps = { }, afterTransfer: { type: Function as unknown as () => ((targetOption: TState) => void) + }, + onDragend: { + type: Function as unknown as () => ((direction: string, dragItem: IItem, dropItem: IItem) => void) } } diff --git a/packages/devui-vue/devui/transfer/src/transfer-base.tsx b/packages/devui-vue/devui/transfer/src/transfer-base.tsx index 10ec9f607d..aecd7a065f 100644 --- a/packages/devui-vue/devui/transfer/src/transfer-base.tsx +++ b/packages/devui-vue/devui/transfer/src/transfer-base.tsx @@ -1,23 +1,31 @@ -import { defineComponent, computed } from 'vue' +import { defineComponent, computed, ref, SetupContext } from 'vue' import { transferBaseProps, TransferBaseClass, TransferBaseProps } from '../common/use-transfer-base' import DCheckbox from '../../checkbox/src/checkbox' import DCheckboxGroup from '../../checkbox/src/checkbox-group' import DSearch from '../../search/src/search' -import DTooltip from '../../tooltip/src/tooltip' +import DTransferDrag from './transfer-drag-item' +import DTransfeCheckbox from './transfer-checkbox' export default defineComponent({ name: 'DTransferBase', components: { DSearch, DCheckboxGroup, DCheckbox, - DTooltip + DTransferDrag, + DTransfeCheckbox }, props: transferBaseProps, - setup(props: TransferBaseProps, ctx) { + setup(props: TransferBaseProps, ctx: SetupContext) { /** data start **/ const modelValues = computed(() => props.checkedValues as Array) + const dragWrapClass = computed(() => { + const isDrag = props.isSourceDroppable || props.isTargetDroppable + return `devui-transfer-panel-body-list devui-transfer-panel-body-${isDrag ? '' : 'no'}drag` + }) const searchQuery = computed(() => props.filter) const baseClass = TransferBaseClass(props) + const dropItem = ref(null) + /** data end **/ /** watch start **/ @@ -26,26 +34,60 @@ export default defineComponent({ /** methods start **/ const updateSearchQuery = (val: string): void => ctx.emit('changeQuery', val) - const renderCheckbox = (props, key, showTooltip = false, tooltipPosition = 'top') => { - const checkbox = - - return !showTooltip ? checkbox : {checkbox} + const renderCheckboxGroup = () => { + return ctx.emit('updateCheckeds', values) + }> + { + props.sourceOption.map((item, idx) => { + return + + }) + } + } + + const renderDragCheckboxGroup = () => { + return ctx.emit('updateCheckeds', values) + }> + { + props.sourceOption.map((item, idx) => { + return { + dropItem.value = item + }} + onDragend={(event, dragItem) => { + props.onDragend && props.onDragend(dragItem, dropItem.value) + }} /> + }) + } + + } + /** methods start **/ return { baseClass, searchQuery, + dragWrapClass, modelValues, + dropItem, updateSearchQuery, - renderCheckbox + renderCheckboxGroup, + renderDragCheckboxGroup } }, render() { @@ -59,11 +101,12 @@ export default defineComponent({ updateSearchQuery, search, searchQuery, - modelValues, + dragWrapClass, height, - showTooltip, - tooltipPosition, - renderCheckbox, + isSourceDroppable, + isTargetDroppable, + renderCheckboxGroup, + renderDragCheckboxGroup, } = this return ( @@ -86,19 +129,11 @@ export default defineComponent({ {search && } -
+
{ - sourceOption.length ? this.$emit('updateCheckeds', values)}> - { - sourceOption.map((item, idx) => { - return renderCheckbox(item, idx, showTooltip, tooltipPosition) - }) - } - : -
无数据
+ sourceOption.length ? + (isSourceDroppable || isTargetDroppable ? renderDragCheckboxGroup() : renderCheckboxGroup()) + :
无数据
}
diff --git a/packages/devui-vue/devui/transfer/src/transfer-checkbox.tsx b/packages/devui-vue/devui/transfer/src/transfer-checkbox.tsx new file mode 100644 index 0000000000..554277da83 --- /dev/null +++ b/packages/devui-vue/devui/transfer/src/transfer-checkbox.tsx @@ -0,0 +1,42 @@ +import { defineComponent } from 'vue' +import DCheckbox from '../../checkbox/src/checkbox' +import DTooltip from '../../tooltip/src/tooltip' +import transferCheckboxProps, { TransferCheckboxProps } from '../common/use-transfer-checkbox' + +export default defineComponent({ + name: 'DTransferCheckbox', + components: { + DCheckbox, + DTooltip + }, + props: transferCheckboxProps, + setup(props: TransferCheckboxProps) { + /** data start **/ + const renderCheckbox = () => { + return + + } + /** data end **/ + + /** watch start **/ + /** watch end **/ + + /** methods start **/ + /** methods end **/ + + return () => { + return ( + !props.showTooltip ? renderCheckbox() : + {renderCheckbox()} + + ) + } + } +}) \ No newline at end of file diff --git a/packages/devui-vue/devui/transfer/src/transfer-drag-item.tsx b/packages/devui-vue/devui/transfer/src/transfer-drag-item.tsx new file mode 100644 index 0000000000..bb104fd3c4 --- /dev/null +++ b/packages/devui-vue/devui/transfer/src/transfer-drag-item.tsx @@ -0,0 +1,134 @@ +import { defineComponent, ref, onUnmounted } from 'vue' +import transferDragProps, { TransferDragProps } from '../common/use-transfer-drag' +import DTransfeCheckbox from './transfer-checkbox' +import '@devui-design/icons/icomoon/devui-icon.css' + +export default defineComponent({ + name: 'DTransferDrag', + components: { + DTransfeCheckbox + }, + props: transferDragProps, + setup(props: TransferDragProps) { + /** data start **/ + const dragRef = ref(null) + const dragHighlight = ref(false) + const dragOverNodeKey = ref('') + const dropPosition = ref(null) + const dragTimer = ref(null) + /** data end **/ + + /** watch start **/ + /** watch end **/ + + /** methods start **/ + /** + * calcDropPosition: 根据event计算位置 + * event: event对象 + */ + const calcDropPosition = (event): number => { + const { clientY } = event; + const { top, bottom, height } = dragRef.value.getBoundingClientRect(); + const des = Math.max(height * 0.25, 2); + + if (clientY <= top + des) { + return -1; + } + if (clientY >= bottom - des) { + return 1; + } + return 0; + } + /** + * resetState: 重置属性 + */ + const resetState = () => { + dragOverNodeKey.value = '' + dropPosition.value = null + dragHighlight.value = null + } + /** methods end **/ + + /** 生命周期 start **/ + onUnmounted(() => { + clearTimeout(dragTimer.value) + }) + /** 生命周期 end **/ + + return () => { + const state = dragOverNodeKey.value === props.itemData.key + return ( +
{ + event.preventDefault(); + event.stopPropagation(); + clearTimeout(dragTimer.value) + const curDropPosition = calcDropPosition(event) + if (props.itemData.key === dragOverNodeKey.value && curDropPosition === 0) { + resetState() + return + } + dragTimer.value = setTimeout(() => { + dragOverNodeKey.value = props.itemData.key + dropPosition.value = curDropPosition + }, 0); + props.onDragenter && props.onDragenter(event, props.itemData) + }} + onDragover={event => { + event.preventDefault() + event.stopPropagation() + if (props.itemData.key === dragOverNodeKey.value) { + const curDropPosition = calcDropPosition(event) + if (curDropPosition === dropPosition.value) { + return + } + dropPosition.value = curDropPosition; + } + props.onDragover && props.onDragover(event, props.itemData) + }} + onDragleave={event => { + event.stopPropagation() + resetState() + props.onDragleave && props.onDragleave(event, props.itemData) + }} + onDrop={event => { + event.preventDefault() + event.stopPropagation() + resetState() + props.onDrop && props.onDrop(event, props.itemData) + }} + onDragend={event => { + event.stopPropagation() + props.onDragend && props.onDragend(event, props.itemData) + }}> +
{ + event.stopPropagation() + dragHighlight.value = true + props.onDragstart && props.onDragstart(event, props.itemData) + }} + > + + + + + +
+
+ ) + } + } +}) \ No newline at end of file diff --git a/packages/devui-vue/devui/transfer/src/transfer.scss b/packages/devui-vue/devui/transfer/src/transfer.scss index 8a6bb867a2..a1f5234eb9 100644 --- a/packages/devui-vue/devui/transfer/src/transfer.scss +++ b/packages/devui-vue/devui/transfer/src/transfer.scss @@ -4,7 +4,7 @@ $devui-transfer-border-color: #adb0b8; $devui-transfer-border-radius: 2px; $devui-transfer-header-height: 40px; $devui-transfer-header-border-line-color:#dfe1e6; -$devui-transfer-body-list-item-height: 36px; +$devui-transfer-body-list-item-height: 32px; .devui-transfer { display: flex; @@ -52,13 +52,14 @@ $devui-transfer-body-list-item-height: 36px; &-list { overflow: auto; width: 100%; - padding: 0 20px; &-item { height: $devui-transfer-body-list-item-height; line-height: $devui-transfer-body-list-item-height; - width: min-content; - max-width: 100%; + display: flex; + align-items: center; + border-top: 2px solid transparent; + border-bottom: 2px solid transparent; label { text-overflow: ellipsis; @@ -68,14 +69,25 @@ $devui-transfer-body-list-item-height: 36px; } } + &-drag{ + width: 100%; + display: flex; + align-items: center; + &__icon { + padding: 0 4px; + visibility: hidden; + height: 28px; + display: flex; + align-items: center; + } + } + &-drag:hover .devui-transfer-panel-body-list-drag__icon{ + visibility: visible; + } + &-tooltip { - // display: flex; - // max-width: calc(100% - 20px); - // overflow: hidden; - // text-overflow: ellipsis; - // white-space: nowrap; .slotElement { - max-width: 100%; + display: flex; } } @@ -87,6 +99,9 @@ $devui-transfer-body-list-item-height: 36px; color: $devui-disabled-text; } } + &-nodrag{ + padding: 0 20px; + } } &-operation { @@ -98,7 +113,6 @@ $devui-transfer-body-list-item-height: 36px; &-group { width: 36px; - &-left .devui-btn, &-right .devui-btn { width: 36px; @@ -114,4 +128,16 @@ $devui-transfer-body-list-item-height: 36px; } } } + &-drag-dragging{ + background-color: $devui-brand-foil; + } + &-drag-over{ + background-color: $devui-brand-hover; + } +} +.devui-transfer–drag-over-top{ + border-top-color: $devui-brand-active; +} +.devui-transfer–drag-over-bottom { + border-bottom-color: $devui-brand-active; } diff --git a/packages/devui-vue/devui/transfer/src/transfer.tsx b/packages/devui-vue/devui/transfer/src/transfer.tsx index e857d12b82..9fcf636bc0 100644 --- a/packages/devui-vue/devui/transfer/src/transfer.tsx +++ b/packages/devui-vue/devui/transfer/src/transfer.tsx @@ -1,5 +1,5 @@ import { defineComponent, reactive, watch, ref, SetupContext } from 'vue' -import { TState } from '../types' +import { TState, IItem } from '../types' import DTransferBase from './transfer-base' import DTransferOperation from './transfer-operation' import { initState } from '../common/use-transfer-base' @@ -39,7 +39,7 @@ export default defineComponent({ watch( () => leftOptions.keyword, - (nVal: string): void => { + (): void => { searchFilterData(leftOptions) } ) @@ -57,7 +57,7 @@ export default defineComponent({ watch( () => rightOptions.keyword, - (nVal: string): void => { + (): void => { searchFilterData(rightOptions) }, ) @@ -155,6 +155,14 @@ export default defineComponent({ const isFunction = (type: string): boolean => { return props[type] && typeof props[type] === 'function' } + + const dataSort = (target: TState, dragItem: IItem, dropItem: IItem, direction: string) => { + const startIndex = target.filterData.findIndex(item => item.key === dragItem.key) + const endIndex = target.filterData.findIndex(item => item.key === dropItem.key) + target.filterData.splice(endIndex, 1, dragItem) + target.filterData.splice(startIndex, 1, dropItem) + props.onDragend && props.onDragend(direction, dragItem, dropItem) + } /** methods end **/ return () => { @@ -172,6 +180,7 @@ export default defineComponent({ allCount={leftOptions.data.length} showTooltip={props.showTooltip} tooltipPosition={props.tooltipPosition} + isSourceDroppable={props.isSourceDroppable} v-slots={ { header: headerSlot(ctx, 'left'), @@ -181,6 +190,7 @@ export default defineComponent({ onChangeAllSource={(value) => changeAllSource(leftOptions, value)} onUpdateCheckeds={updateLeftCheckeds} onChangeQuery={(value) => changeQueryHandle(leftOptions, 'left', value)} + onDragend={(dragItem, dropItem) => dataSort(leftOptions, dragItem, dropItem, 'left')} /> changeAllSource(rightOptions, value)} onUpdateCheckeds={updateRightCheckeds} onChangeQuery={(value) => changeQueryHandle(rightOptions, 'right', value)} + onDragend={(dragItem, dropItem) => dataSort(rightOptions, dragItem, dropItem, 'right')} /> } diff --git a/packages/devui-vue/docs/components/transfer/index.md b/packages/devui-vue/docs/components/transfer/index.md index 2a1ae1409e..23ddee3462 100644 --- a/packages/devui-vue/docs/components/transfer/index.md +++ b/packages/devui-vue/docs/components/transfer/index.md @@ -7,7 +7,7 @@ 需要在多个可选项中进行多选时。穿梭选择框可用只管的方式在两栏中移动数据,完成选择行为。其中左边一栏为 source,右边一栏为 target。最终返回两栏的数据,提供给开发者使用。 ### 基本用法 - +穿梭框基本用法。 :::demo ```vue @@ -67,6 +67,24 @@ export default defineComponent({ value: '福建', disabled: false, }, + + ] + const originTarget = [ + { + key: '南充', + value: '南充', + disabled: false, + }, + { + key: '广元', + value: '广元', + disabled: false, + }, + { + key: '绵阳', + value: '绵阳', + disabled: false, + }, { key: '大连', value: '大连', @@ -78,6 +96,95 @@ export default defineComponent({ disabled: false, }, ] + + const options = reactive({ + titles: ['sourceHeader', 'targetHeader'], + source: originSource, + target: originTarget, + originSource, + originTarget, + isSearch: true, + modelValues: ['深圳', '成都', '绵阳'] + }) + + return { + options + } + } +}) + +``` + +::: + + +### 拖拽排序 + +可以对穿梭框源和目标框的数据进行排序。 + +:::demo + +```vue + + ``` -::: +::: ### 自定义穿梭框 - +可以对穿梭框内容的显示进行自定义。 :::demo ```vue @@ -350,6 +469,7 @@ export default defineComponent({ height: 36px; line-height: 36px; border-bottom: 1px solid #dfe1e6; + align-items: center; } .custom-transfer__body__list__part { width: 30%; @@ -377,6 +497,8 @@ export default defineComponent({ ::: + + ### API d-transfer 参数 @@ -397,4 +519,13 @@ d-transfer 事件 | transferToTarget | `EventEmitter<{sourceOption, targetOption}>` | 当点击左穿梭时,返回穿梭框源和目标数据; | [基本用法](#基本用法) | | searching | `EventEmitter<{direction, keyword}>` | 当搜索时触发,返回目标穿梭框和搜索文字,不设置此事件则会使用默认方法; | [基本用法](#基本用法) | | transferring | `EventEmitter` | 当穿梭时触发,返回目标穿梭框,不设置此事件则会使用默认方法; | [基本用法](#基本用法) | -| afterTransfer | `EventEmitter` | 当穿梭完成后,返回目标穿梭框,不设置transferEvent才会触发; | [基本用法](#基本用法) | \ No newline at end of file +| afterTransfer | `EventEmitter` | 当穿梭完成后,返回目标穿梭框,不设置transferEvent才会触发; | [基本用法](#基本用法) | +| onDragEnd | `(direction: string, dragItem: TransferItem, dropItem: TransferItem) => void` | 节点结束拖拽的回调; | [基本用法](#基本用法) | + + +d-transfer.Item +| **属性** | **类型** | **默认** | **说明** | **跳转 Demo** | +| ------------------ | ------------------------------------------------------------ | ------------------------- | ------------------------------------------------------------ | ---------------------------- | +| key | `string (required)` | - | 选项的键值(唯一标识符) | [基本用法](#基本用法) | +| value | `string (required)` | - | 选项对应的值 | [基本用法](#基本用法) | +| disabled | `boolean` | - | 是否禁用此选项 | [基本用法](#基本用法) | \ No newline at end of file From 4b869584ebb63c6206159569ffc787db33a5a8a4 Mon Sep 17 00:00:00 2001 From: Echo Date: Sat, 25 Dec 2021 22:27:23 +0800 Subject: [PATCH 3/9] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3ExtractPropTypes?= =?UTF-8?q?=E3=80=81PropType=E5=BC=95=E7=94=A8=E4=B8=8D=E6=AD=A3=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devui-vue/devui/transfer/common/use-transfer-checkbox.ts | 2 +- packages/devui-vue/devui/transfer/common/use-transfer-common.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts b/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts index 1f2ec1189b..1507a161ad 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts @@ -1,4 +1,4 @@ -import { ExtractPropTypes } from '@vue/runtime-core' +import { ExtractPropTypes } from 'vue' import { IItem } from '../types' import { transferCommon } from './use-transfer-common' diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-common.ts b/packages/devui-vue/devui/transfer/common/use-transfer-common.ts index 6f4e75b295..0ad911eb31 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer-common.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer-common.ts @@ -1,4 +1,4 @@ -import { PropType } from '@vue/runtime-core' +import { PropType } from 'vue' import { IItem } from '../types' export const transferCommon = { From 358e337ca8f311a4151c20f142521d8282234c5a Mon Sep 17 00:00:00 2001 From: Echo Date: Sat, 25 Dec 2021 22:29:58 +0800 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=E7=A9=BF=E6=A2=AD=E6=A1=86?= =?UTF-8?q?=E5=85=A8=E9=80=89=E5=A2=9E=E5=8A=A0=E5=8D=8A=E9=80=89=E4=B8=AD?= =?UTF-8?q?=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devui/transfer/src/transfer-base.tsx | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/devui-vue/devui/transfer/src/transfer-base.tsx b/packages/devui-vue/devui/transfer/src/transfer-base.tsx index aecd7a065f..29411f83f5 100644 --- a/packages/devui-vue/devui/transfer/src/transfer-base.tsx +++ b/packages/devui-vue/devui/transfer/src/transfer-base.tsx @@ -1,4 +1,4 @@ -import { defineComponent, computed, ref, SetupContext } from 'vue' +import { defineComponent, computed, ref, watch, SetupContext } from 'vue' import { transferBaseProps, TransferBaseClass, TransferBaseProps } from '../common/use-transfer-base' import DCheckbox from '../../checkbox/src/checkbox' import DCheckboxGroup from '../../checkbox/src/checkbox-group' @@ -17,6 +17,7 @@ export default defineComponent({ props: transferBaseProps, setup(props: TransferBaseProps, ctx: SetupContext) { /** data start **/ + const allHalfchecked = ref(false)//ref(props.allChecked) const modelValues = computed(() => props.checkedValues as Array) const dragWrapClass = computed(() => { const isDrag = props.isSourceDroppable || props.isTargetDroppable @@ -29,6 +30,19 @@ export default defineComponent({ /** data end **/ /** watch start **/ + watch( + () => props.checkedNum, + (nVal) => { + if (props.allChecked) { + allHalfchecked.value = !props.allChecked + } else { + allHalfchecked.value = nVal !== 0 + } + }, + { + immediate: true + } + ) /** watch end **/ /** methods start **/ @@ -85,6 +99,7 @@ export default defineComponent({ dragWrapClass, modelValues, dropItem, + allHalfchecked, updateSearchQuery, renderCheckboxGroup, renderDragCheckboxGroup @@ -96,6 +111,7 @@ export default defineComponent({ baseClass, checkedNum, allChecked, + allHalfchecked, sourceOption, allCount, updateSearchQuery, @@ -106,7 +122,7 @@ export default defineComponent({ isSourceDroppable, isTargetDroppable, renderCheckboxGroup, - renderDragCheckboxGroup, + renderDragCheckboxGroup } = this return ( @@ -115,8 +131,11 @@ export default defineComponent({ this.$slots.header ? this.$slots.header() : (
this.$emit('changeAllSource', value)}> + onChange={(value: boolean) => { + this.$emit('changeAllSource', value) + }}> {title}
From d3c4fbd8153f9d7850ec3b3faa54570ef0d39ea8 Mon Sep 17 00:00:00 2001 From: Echo Date: Mon, 10 Jan 2022 21:50:36 +0800 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=E7=A9=BF=E6=A2=AD=E6=A1=86?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0tooltip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/devui-vue/docs/components/transfer/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/devui-vue/docs/components/transfer/index.md b/packages/devui-vue/docs/components/transfer/index.md index 23ddee3462..d843e180ee 100644 --- a/packages/devui-vue/docs/components/transfer/index.md +++ b/packages/devui-vue/docs/components/transfer/index.md @@ -18,6 +18,7 @@ :sourceOption="options.source" :targetOption="options.target" :isSearch="options.isSearch" + :showTooltip="options.showTooltip" > @@ -104,7 +105,8 @@ export default defineComponent({ originSource, originTarget, isSearch: true, - modelValues: ['深圳', '成都', '绵阳'] + modelValues: ['深圳', '成都', '绵阳'], + showTooltip: true }) return { From b0945ff9c4ac183fb5380719f4aee72aa71cd4eb Mon Sep 17 00:00:00 2001 From: Echo Date: Mon, 10 Jan 2022 21:53:41 +0800 Subject: [PATCH 6/9] =?UTF-8?q?docs:=20=E8=BF=9B=E5=BA=A6=E6=9B=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/devui-vue/devui/tooltip/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/devui-vue/devui/tooltip/index.ts b/packages/devui-vue/devui/tooltip/index.ts index a27b320b48..50d3ccd7ca 100644 --- a/packages/devui-vue/devui/tooltip/index.ts +++ b/packages/devui-vue/devui/tooltip/index.ts @@ -1,7 +1,7 @@ import type { App } from 'vue' import Tooltip from './src/tooltip' -Tooltip.install = function(app: App) { +Tooltip.install = function (app: App) { app.component(Tooltip.name, Tooltip) } @@ -10,7 +10,7 @@ export { Tooltip } export default { title: 'Tooltip提示', category: '反馈', - status: '50%', + status: '70%', install(app: App): void { app.use(Tooltip as any) } From 65fcec673683abb4bcf6baadbebced823f522cc2 Mon Sep 17 00:00:00 2001 From: Echo Date: Thu, 27 Jan 2022 22:26:49 +0800 Subject: [PATCH 7/9] =?UTF-8?q?test:=20=E7=A9=BF=E6=A2=AD=E6=A1=86?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E7=94=A8=E6=B3=95=E3=80=81=E6=8B=96=E6=8B=BD?= =?UTF-8?q?=E6=8E=92=E5=BA=8F=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/__snapshots__/card.spec.ts.snap | 39 ++ .../devui/transfer/__tests__/transfer.spec.ts | 438 ++++++++++++++++++ 2 files changed, 477 insertions(+) create mode 100644 packages/devui-vue/devui/card/__tests__/__snapshots__/card.spec.ts.snap create mode 100644 packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts diff --git a/packages/devui-vue/devui/card/__tests__/__snapshots__/card.spec.ts.snap b/packages/devui-vue/devui/card/__tests__/__snapshots__/card.spec.ts.snap new file mode 100644 index 0000000000..76e8d750da --- /dev/null +++ b/packages/devui-vue/devui/card/__tests__/__snapshots__/card.spec.ts.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`card should render correctly 1`] = ` +
+ +
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+
+ +
+
+`; diff --git a/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts b/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts new file mode 100644 index 0000000000..12d78fb110 --- /dev/null +++ b/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts @@ -0,0 +1,438 @@ +import { mount } from '@vue/test-utils'; +import { ref, nextTick } from 'vue' +import DCheckbox from '../../checkbox/src/checkbox'; +import DTooltip from '../../tooltip/src/tooltip'; +import DTransfer from '../src/transfer' + +const SOURCE_DATA = [ + { + key: '北京', + value: '北京', + disabled: false, + }, + { + key: '上海', + value: '上海', + disabled: true, + }, + { + key: '广州', + value: '广州', + disabled: true, + }, + { + key: '深圳', + value: '深圳', + disabled: false, + }, + { + key: '成都', + value: '成都', + disabled: false, + }, + { + key: '武汉', + value: '武汉', + disabled: false, + }, + { + key: '西安', + value: '西安', + disabled: false, + }, + { + key: '福建', + value: '福建', + disabled: false, + } +] +const TARGET_DATA = [ + { + key: '南充', + value: '南充', + disabled: false, + }, + { + key: '广元', + value: '广元', + disabled: false, + }, + { + key: '绵阳', + value: '绵阳', + disabled: false, + }, + { + key: '大连', + value: '大连', + disabled: false, + }, + { + key: '重庆', + value: '重庆', + disabled: false, + } +] + +describe('d-transfer', () => { + it('d-transfer basic work', async () => { + const sourceOption = ref(SOURCE_DATA) + const targetOption = ref(TARGET_DATA) + const wrapper = mount({ + components: { + DTransfer + }, + template: ` + + + `, + setup() { + return { + modelValues: ref(['成都', '绵阳']), + titles: ref(['sourceHeader', 'targetHeader']), + source: sourceOption, + target: targetOption + } + } + }) + + /** + * 测试穿梭框源是否正确渲染 start + */ + expect(wrapper.find('.devui-transfer').exists()).toBeTruthy() + expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8) + expect(wrapper.findAll('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').length).toBe(5) + /** + * 测试穿梭框源是否正确渲染 end + */ + + + /** + * 测试穿梭框源数据中disable start + */ + const disableds = wrapper.findAll('.devui-transfer .devui-transfer-source .disabled') + expect(disableds.length).toBe(2) + expect(disableds.filter(item => ['上海', '广州'].includes(item.text())).length).toBe(2) + /** + * 测试穿梭框源数据中disable end + */ + + + /** + * 测试穿梭框默认选中值 start + */ + await nextTick() + const sourceChecked = wrapper.find('.devui-transfer-source .active') + expect(sourceChecked.text()).toBe('成都') + const targetChecked = wrapper.find('.devui-transfer-target .active') + expect(targetChecked.text()).toBe('绵阳') + /** + * 测试穿梭框默认选中值 end + */ + + + /** + * 测试穿梭框左右穿梭 start + */ + // 源按钮 + const leftButton = wrapper.find('.devui-transfer .devui-transfer-panel-operation-group-left button') + expect(leftButton) + expect(leftButton.attributes('disabled')).toEqual(undefined) + leftButton.trigger('click') + await nextTick() + expect(leftButton.attributes('disabled')).toEqual('') + // 目标按钮 + const rightButton = wrapper.find('.devui-transfer .devui-transfer-panel-operation-group-right button') + expect(rightButton) + expect(rightButton.attributes('disabled')).toEqual(undefined) + rightButton.trigger('click') + await nextTick() + expect(rightButton.attributes('disabled')).toEqual('') + /** + * 测试穿梭框左右穿梭 end + */ + + + /** + * 测试穿梭框左、右全选 start + */ + // 源全选 + const sourceAllInput = wrapper.find('.devui-transfer-source .devui-transfer-panel-header-allChecked .devui-checkbox-input') + sourceAllInput.trigger('click') + await nextTick() + const newSourceAllInput = wrapper.find('.devui-transfer-source .devui-transfer-panel-header-allChecked .devui-checkbox-input') + expect(newSourceAllInput.element.checked).toBeTruthy() + // 目标全选 + const targetAllInput = wrapper.find('.devui-transfer-target .devui-transfer-panel-header-allChecked .devui-checkbox-input') + targetAllInput.trigger('click') + await nextTick() + const newTargetAllInput = wrapper.find('.devui-transfer-target .devui-transfer-panel-header-allChecked .devui-checkbox-input') + expect(newTargetAllInput.element.checked).toBeTruthy() + /** + * 测试穿梭框左、右全选 end + */ + }) + + it('d-transfer searching work', async () => { + const sourceOption = ref(SOURCE_DATA) + const targetOption = ref(TARGET_DATA) + const wrapper = mount({ + components: { + DTransfer + }, + template: ` + + + `, + setup() { + return { + modelValues: ref(['成都', '绵阳']), + titles: ref(['sourceHeader', 'targetHeader']), + source: sourceOption, + target: targetOption, + isSearch: ref(true) + } + } + }) + + /** + * 测试搜索功能 start + */ + // 源搜索功能 + expect(wrapper.find('.devui-transfer-source .devui-search').exists()).toBe(true) + const sourceSearch = wrapper.find('.devui-transfer-source .devui-search input[type="text"]') + const sourceSearchClear = wrapper.find('.devui-transfer-source .devui-search .devui-search__clear') + expect(sourceSearchClear.exists()).toBe(false) + sourceSearch.setValue('成都') + await nextTick() + expect(sourceSearch.element.value).toBe('成都') + expect(wrapper.find('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').text()).toBe('成都') + const newSourceSearchClear = wrapper.find('.devui-transfer-source .devui-search .devui-search__clear') + expect(newSourceSearchClear.exists()).toBe(true) + newSourceSearchClear.trigger('click') + await nextTick() + expect(wrapper.find('.devui-transfer-source .devui-search input[type="text"]').element.value).toBe('') + + // 目标搜索功能 + expect(wrapper.find('.devui-transfer-target .devui-search').exists()).toBe(true) + const targetSearch = wrapper.find('.devui-transfer-target .devui-search input[type="text"]') + const targetSearchClear = wrapper.find('.devui-transfer-target .devui-search .devui-search__clear') + expect(targetSearchClear.exists()).toBe(false) + targetSearch.setValue('广元') + await nextTick() + expect(targetSearch.element.value).toBe('广元') + expect(wrapper.find('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').text()).toBe('广元') + const newTargetSearchClear = wrapper.find('.devui-transfer-target .devui-search .devui-search__clear') + expect(newTargetSearchClear.exists()).toBe(true) + newTargetSearchClear.trigger('click') + await nextTick() + expect(wrapper.find('.devui-transfer-target .devui-search input[type="text"]').element.value).toBe('') + /** + * 测试搜索功能 end + */ + + }) + + // it('d-transfer tooltips work', async () => { + // const sourceOption = ref(SOURCE_DATA) + // const targetOption = ref(TARGET_DATA) + // const wrapper = mount({ + // components: { + // DTransfer + // }, + // template: ` + // + // + // `, + // setup() { + // return { + // modelValues: ref(['成都', '绵阳']), + // titles: ref(['sourceHeader', 'targetHeader']), + // source: sourceOption, + // target: targetOption, + // isShowTooltip: ref(true) + // } + // } + // }) + + // /** + // * 测试穿梭框渲染 start + // */ + // expect(wrapper.find('.devui-transfer-source').exists()).toBe(true) + // expect(wrapper.find('.devui-transfer-target').exists()).toBe(true) + // expect(wrapper.findAll('.devui-transfer-source .devui-tooltip').length).toBe(8) + // expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8) + // /** + // * 测试穿梭框渲染 end + // */ + + + // /** + // * 测试穿梭框tooltip start + // */ + // expect(wrapper.find('.devui-transfer-source').exists()).toBe(true) + // expect(wrapper.find('.devui-transfer-target').exists()).toBe(true) + // expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8) + // expect(wrapper.findAll('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').length).toBe(5) + // const sourceTooltips = wrapper.findAll('.devui-transfer-source .devui-tooltip') + // const targetTooltips = wrapper.findAll('.devui-transfer-target .devui-tooltip') + // expect(sourceTooltips.length).toBe(8) + // expect(targetTooltips.length).toBe(5) + // expect(sourceTooltips[0].find('.tooltip').exists()).toBe(false) + + + // const sourceBody = wrapper.find('.devui-transfer-source .devui-transfer-panel-body') + // const checkboxC = sourceBody.findComponent(DTooltip) + // const slotElement = checkboxC.find('.devui-checkbox-column-margin') + // slotElement.trigger('mouseenter') + // console.log(slotElement.classes()) + // await nextTick() + // console.log(checkboxC.find('.tooltip')) + + + + // /** + // * 测试穿梭框tooltip end + // */ + // }) + + it('d-transfer source drag work', async () => { + const sourceOption = ref(SOURCE_DATA) + const targetOption = ref(TARGET_DATA) + const wrapper = mount({ + components: { + DTransfer + }, + template: ` + + + `, + setup() { + return { + modelValues: ref(['成都', '绵阳']), + titles: ref(['sourceHeader', 'targetHeader']), + source: sourceOption, + target: targetOption, + isSourceDroppable: ref(true) + } + } + }) + + + // /** + // * 测试穿梭框拖拽排序 start + // */ + // const startDragItemIndex = sourceOption.value.findIndex(item => item.value === '成都') + // const startDropItemIndex = sourceOption.value.findIndex(item => item.value === '上海') + // const dragItemValue = sourceOption.value[startDragItemIndex] + // const dropItemValue = sourceOption.value[startDropItemIndex] + // const dataSort = (target, dragItem, dropItem) => { + // const startIndex = target.findIndex(item => item.key === dragItem.key) + // const endIndex = target.findIndex(item => item.key === dropItem.key) + // target.splice(endIndex, 1, dragItem) + // target.splice(startIndex, 1, dropItem) + // } + // dataSort(sourceOption.value, dragItemValue, dropItemValue) + // await nextTick() + // const endDragItemIndex = sourceOption.value.findIndex(item => item.value === '成都') + // const endDropItemIndex = sourceOption.value.findIndex(item => item.value === '上海') + // // 4 1 // 1 4 + // /** + // * 测试穿梭框拖拽排序 end + // */ + /** + * 测试穿梭框拖拽排序 start + */ + const left = wrapper.find('.devui-transfer-source') + const leftTransfer = left.findComponent({ name: 'DTransferBase' }) + const leftOption = leftTransfer.props().sourceOption + const startDragItemIndex = leftOption.findIndex(item => item.value === '成都') + const startDropItemIndex = leftOption.findIndex(item => item.value === '上海') + expect(startDragItemIndex).toBe(4) + expect(startDropItemIndex).toBe(1) + leftTransfer.props().onDragend(leftOption[startDragItemIndex], leftOption[startDropItemIndex]) + await nextTick() + const endDragItemIndex = leftOption.findIndex(item => item.value === '成都') + const endDropItemIndex = leftOption.findIndex(item => item.value === '上海') + expect(endDragItemIndex).toBe(1) + expect(endDropItemIndex).toBe(4) + /** + * 测试穿梭框拖拽排序 end + */ + }) + + it('d-transfer target drag work', async () => { + const sourceOption = ref(SOURCE_DATA) + const targetOption = ref(TARGET_DATA) + const wrapper = mount({ + components: { + DTransfer + }, + template: ` + + + `, + setup() { + return { + modelValues: ref(['成都', '绵阳']), + titles: ref(['sourceHeader', 'targetHeader']), + source: sourceOption, + target: targetOption, + isSourceDroppable: ref(true) + } + } + }) + + + /** + * 测试穿梭框拖拽排序 start + */ + const transfer = wrapper.findComponent({ name: 'DTransfer' }) + const rightTransfer = wrapper.find('.devui-transfer-target').findComponent({ name: 'DTransferBase' }) + const rightOption = transfer.props().targetOption + const startDragItemIndex = rightOption.findIndex(item => item.value === '大连') + const startDropItemIndex = rightOption.findIndex(item => item.value === '广元') + expect(startDragItemIndex).toBe(3) + expect(startDropItemIndex).toBe(1) + rightTransfer.props().onDragend(rightOption[startDragItemIndex], rightOption[startDropItemIndex]) + await nextTick() + const endDragItemIndex = rightOption.findIndex(item => item.value === '大连') + const endDropItemIndex = rightOption.findIndex(item => item.value === '广元') + expect(endDragItemIndex).toBe(3) + expect(endDropItemIndex).toBe(1) + /** + * 测试穿梭框拖拽排序 end + */ + }) +}) From 065e8749fa3c1ab8f0c9686d1d03096894f86d17 Mon Sep 17 00:00:00 2001 From: Echo Date: Mon, 31 Jan 2022 17:43:54 +0800 Subject: [PATCH 8/9] =?UTF-8?q?feat:=20=E7=A9=BF=E6=A2=AD=E6=A1=86?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devui/transfer/__tests__/transfer.spec.ts | 292 ++++++++++++++++-- .../docs/components/transfer/index.md | 8 +- 2 files changed, 275 insertions(+), 25 deletions(-) diff --git a/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts b/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts index 12d78fb110..627014cb08 100644 --- a/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts +++ b/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts @@ -1,7 +1,9 @@ import { mount } from '@vue/test-utils'; -import { ref, nextTick } from 'vue' +import { ref, reactive, watch, nextTick } from 'vue' import DCheckbox from '../../checkbox/src/checkbox'; +import DCheckboxGroup from '../../checkbox/src/checkbox-group' import DTooltip from '../../tooltip/src/tooltip'; +import DButton from '../../button/src/button'; import DTransfer from '../src/transfer' const SOURCE_DATA = [ @@ -244,6 +246,273 @@ describe('d-transfer', () => { }) + it('d-transfer customTransfer drag work', async () => { + const leftData = [ + { + key: '1', + value: 'Mark', + age: 11, + disabled: false, + }, + { + key: '2', + value: 'Jacob', + age: 12, + disabled: false, + }, + { + key: '3', + value: 'Danni', + age: 13, + disabled: false, + }, + { + key: '4', + value: 'green', + age: 14, + disabled: false, + }, + { + key: '5', + value: 'po', + age: 15, + disabled: false, + }, + { + key: '6', + value: 'Book', + age: 16, + disabled: false, + } + ] + const rightData = [ + { + key: '21', + value: 'john', + age: 17, + disabled: false, + }, + { + key: '22', + value: 'Joke', + age: 28, + disabled: false, + }, + { + key: '23', + value: 'Echo', + age: 18, + disabled: false, + } + ] + const leftOptions = reactive({ + allChecked: false, + filterData: leftData, + checkedValues: [], + disabled: true, + }); + + const rightOptions = reactive({ + allChecked: false, + filterData: rightData, + checkedValues: [], + disabled: true + }) + const wrapper = mount({ + components: { + DTransfer, + DCheckbox, + DCheckboxGroup, + DButton, + }, + template: ` + + + + + + + + `, + setup() { + watch( + () => leftOptions.checkedValues, + (nVal) => { + console.log('fetch', leftOptions.checkedValues) + rightOptions.disabled = nVal.length !== 0 ? false : true + leftOptions.allChecked = isEqual(nVal, leftOptions.filterData) + }, + { + deep: true + } + ) + + watch( + () => rightOptions.checkedValues, + (nVal) => { + console.log('right', rightOptions.checkedValues) + leftOptions.disabled = nVal.length !== 0 ? false : true + rightOptions.allChecked = isEqual(nVal, rightOptions.filterData) + }, + { + deep: true + } + ) + + const isEqual = (source, target) => { + return target.length !== 0 && source.length === target.length + } + + const changeAllSource = (source) => { + if (source.allChecked) { + source.checkedValues = source.filterData.map(item => item.value) + } else { + source.checkedValues = [] + } + } + + const updateRightFilterData = () => { + rightOptions.filterData = rightOptions.filterData.filter(item => { + const hasItem = rightOptions.checkedValues.includes(item.value) + if (hasItem) { + leftOptions.filterData.push(item) + } + return !hasItem + }) + rightOptions.checkedValues = [] + } + + const updateLeftFilterData = () => { + leftOptions.filterData = leftOptions.filterData.filter(item => { + const hasItem = leftOptions.checkedValues.includes(item.value) + if (hasItem) { + rightOptions.filterData.push(item) + } + return !hasItem + }) + leftOptions.checkedValues = [] + } + return { + leftOptions, + rightOptions, + changeAllSource, + updateRightFilterData, + updateLeftFilterData + } + } + }) + + /** + * 测试自定义穿梭框 start + */ + const sourceWrapper = wrapper.find('.devui-transfer-source') + const tragetWrapper = wrapper.find('.devui-transfer-target') + const leftHeader = sourceWrapper.find('.custom-transfer__header') + const rightHeader = tragetWrapper.find('.custom-transfer__header') + expect(leftHeader.text()).toBe('Customize Source Header') + expect(rightHeader.text()).toBe('Customize Target Header') + + const buttons = wrapper.findAllComponents({ name: 'DButton' }) + expect(buttons[0].props().disabled).toBe(true) + expect(buttons[1].props().disabled).toBe(true) + const leftLabel = sourceWrapper.findAll('.devui-checkbox-group label') + expect(leftLabel.length).toBe(6) + expect(tragetWrapper.findAll('.devui-checkbox-group label').length).toBe(3) + leftLabel[0].trigger('click') + await nextTick() + leftLabel[1].trigger('click') + await nextTick() + expect(buttons[1].props().disabled).toBe(false) + wrapper.findAll('.devui-btn')[1].trigger('click') + await nextTick() + expect(sourceWrapper.findAll('.devui-checkbox-group label').length).toBe(4) + expect(tragetWrapper.findAll('.devui-checkbox-group label').length).toBe(5) + + const rightLabel = tragetWrapper.findAll('.devui-checkbox-group label') + rightLabel[0].trigger('click') + await nextTick() + rightLabel[1].trigger('click') + await nextTick() + rightLabel[2].trigger('click') + await nextTick() + rightLabel[3].trigger('click') + await nextTick() + rightLabel[4].trigger('click') + await nextTick() + expect(tragetWrapper.findAll('.active').length).toBe(4) + expect(buttons[0].props().disabled).toBe(false) + wrapper.findAll('.devui-btn')[0].trigger('click') + await nextTick() + expect(sourceWrapper.findAll('.devui-checkbox-group label').length).toBe(9) + expect(tragetWrapper.findAll('.devui-checkbox-group label').length).toBe(0) + /** + * 测试自定义穿梭框 end + */ + }) + // it('d-transfer tooltips work', async () => { // const sourceOption = ref(SOURCE_DATA) // const targetOption = ref(TARGET_DATA) @@ -343,27 +612,6 @@ describe('d-transfer', () => { }) - // /** - // * 测试穿梭框拖拽排序 start - // */ - // const startDragItemIndex = sourceOption.value.findIndex(item => item.value === '成都') - // const startDropItemIndex = sourceOption.value.findIndex(item => item.value === '上海') - // const dragItemValue = sourceOption.value[startDragItemIndex] - // const dropItemValue = sourceOption.value[startDropItemIndex] - // const dataSort = (target, dragItem, dropItem) => { - // const startIndex = target.findIndex(item => item.key === dragItem.key) - // const endIndex = target.findIndex(item => item.key === dropItem.key) - // target.splice(endIndex, 1, dragItem) - // target.splice(startIndex, 1, dropItem) - // } - // dataSort(sourceOption.value, dragItemValue, dropItemValue) - // await nextTick() - // const endDragItemIndex = sourceOption.value.findIndex(item => item.value === '成都') - // const endDropItemIndex = sourceOption.value.findIndex(item => item.value === '上海') - // // 4 1 // 1 4 - // /** - // * 测试穿梭框拖拽排序 end - // */ /** * 测试穿梭框拖拽排序 start */ diff --git a/packages/devui-vue/docs/components/transfer/index.md b/packages/devui-vue/docs/components/transfer/index.md index d843e180ee..0ac5807b3b 100644 --- a/packages/devui-vue/docs/components/transfer/index.md +++ b/packages/devui-vue/docs/components/transfer/index.md @@ -509,9 +509,11 @@ d-transfer 参数 | sourceOption | `Array` | [] | 可选参数,穿梭框源数据 | [基本用法](#基本用法) | | targetOption | `Array` | [] | 可选参数,穿梭框目标数据 | [基本用法](#基本用法) | | titles | `Array` | [] | 可选参数,穿梭框标题 | [基本用法](#基本用法) | -| height | `Array` | 320px | 可选参数,穿梭框高度 | [基本用法](#基本用法) | -| isSearch | `Array` | true | 可选参数,是否可以搜索 | [基本用法](#基本用法) | -| disabled | `Array` | false | 可选参数 穿梭框禁止使用 | [基本用法](#基本用法) | +| height | `String` | 320px | 可选参数,穿梭框高度 | [基本用法](#基本用法) | +| isSearch | `Boolean` | true | 可选参数,是否可以搜索 | [基本用法](#基本用法) | +| disabled | `Boolean` | false | 可选参数 穿梭框禁止使用 | [基本用法](#基本用法) | +| isSourceDroppable | `Boolean` | false | 可选参数,源是否可以拖拽 | [基本用法](#拖拽排序) | +| isTargetDroppable | `Boolean` | false | 可选参数,目标是否可以拖拽 | [基本用法](#拖拽排序) | | beforeTransfer | `(sourceOption, targetOption) => boolean \| Promise` |- | 可选参数 穿梭框禁止使用 | [基本用法](#基本用法) | d-transfer 事件 From 430b4f516af2b7d1c19b18df7096ab4a21fdcde6 Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 22 Feb 2022 22:35:58 +0800 Subject: [PATCH 9/9] =?UTF-8?q?docs:=20=E6=96=87=E6=A1=A3=E6=9B=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/devui-vue/docs/components/transfer/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/devui-vue/docs/components/transfer/index.md b/packages/devui-vue/docs/components/transfer/index.md index 0ac5807b3b..c080e43df4 100644 --- a/packages/devui-vue/docs/components/transfer/index.md +++ b/packages/devui-vue/docs/components/transfer/index.md @@ -512,8 +512,8 @@ d-transfer 参数 | height | `String` | 320px | 可选参数,穿梭框高度 | [基本用法](#基本用法) | | isSearch | `Boolean` | true | 可选参数,是否可以搜索 | [基本用法](#基本用法) | | disabled | `Boolean` | false | 可选参数 穿梭框禁止使用 | [基本用法](#基本用法) | -| isSourceDroppable | `Boolean` | false | 可选参数,源是否可以拖拽 | [基本用法](#拖拽排序) | -| isTargetDroppable | `Boolean` | false | 可选参数,目标是否可以拖拽 | [基本用法](#拖拽排序) | +| isSourceDroppable | `Boolean` | false | 可选参数,源是否可以拖拽 | [拖拽排序](#拖拽排序) | +| isTargetDroppable | `Boolean` | false | 可选参数,目标是否可以拖拽 | [拖拽排序](#拖拽排序) | | beforeTransfer | `(sourceOption, targetOption) => boolean \| Promise` |- | 可选参数 穿梭框禁止使用 | [基本用法](#基本用法) | d-transfer 事件 @@ -524,7 +524,7 @@ d-transfer 事件 | searching | `EventEmitter<{direction, keyword}>` | 当搜索时触发,返回目标穿梭框和搜索文字,不设置此事件则会使用默认方法; | [基本用法](#基本用法) | | transferring | `EventEmitter` | 当穿梭时触发,返回目标穿梭框,不设置此事件则会使用默认方法; | [基本用法](#基本用法) | | afterTransfer | `EventEmitter` | 当穿梭完成后,返回目标穿梭框,不设置transferEvent才会触发; | [基本用法](#基本用法) | -| onDragEnd | `(direction: string, dragItem: TransferItem, dropItem: TransferItem) => void` | 节点结束拖拽的回调; | [基本用法](#基本用法) | +| onDragEnd | `(direction: string, dragItem: TransferItem, dropItem: TransferItem) => void` | 节点结束拖拽的回调; | [拖拽排序](#拖拽排序) | d-transfer.Item