|
@@ -1,685 +1,719 @@
|
|
|
-import {ElTooltip, useFocusController, useFormItem, useFormItemInputId, useNamespace} from "element-plus";
|
|
|
-import {useCompRef} from "@/utils/useCompRef";
|
|
|
-import XEUtils, {filter, isArray, isEqual, isFunction, isNumber, isString} from "xe-utils";
|
|
|
-import {useResizeObserver} from "@vueuse/core";
|
|
|
-import {stringNotBlank} from "@/utils/blank-utils";
|
|
|
-import {listFilter} from "@/utils/list-utlis";
|
|
|
+import {
|
|
|
+ ElTooltip,
|
|
|
+ useFocusController,
|
|
|
+ useFormItem,
|
|
|
+ useFormItemInputId,
|
|
|
+ useNamespace,
|
|
|
+} from "element-plus";
|
|
|
+import { useCompRef } from "@/utils/useCompRef";
|
|
|
+import XEUtils, {
|
|
|
+ filter,
|
|
|
+ isArray,
|
|
|
+ isEqual,
|
|
|
+ isFunction,
|
|
|
+ isNumber,
|
|
|
+ isString,
|
|
|
+} from "xe-utils";
|
|
|
+import { useResizeObserver } from "@vueuse/core";
|
|
|
+import { stringNotBlank } from "@/utils/blank-utils";
|
|
|
+import { listFilter } from "@/utils/list-utlis";
|
|
|
//@ts-ignore
|
|
|
-import Sortable from 'sortablejs'
|
|
|
+import Sortable from "sortablejs";
|
|
|
import {
|
|
|
- WritableComputedRef,
|
|
|
- ref,
|
|
|
- computed,
|
|
|
- watch,
|
|
|
- reactive,
|
|
|
- nextTick,
|
|
|
- ExtractPropTypes,
|
|
|
- onMounted
|
|
|
+ WritableComputedRef,
|
|
|
+ ref,
|
|
|
+ computed,
|
|
|
+ watch,
|
|
|
+ reactive,
|
|
|
+ nextTick,
|
|
|
+ ExtractPropTypes,
|
|
|
+ onMounted,
|
|
|
} from "vue";
|
|
|
-import {isPromise} from "@/utils/public";
|
|
|
+import { isPromise } from "@/utils/public";
|
|
|
import CyComboGridProps from "@/components/cy/combo-grid/src/CyComboGridProps";
|
|
|
|
|
|
const isKorean = (text: string) =>
|
|
|
- /([\uAC00-\uD7AF\u3130-\u318F])+/gi.test(text)
|
|
|
+ /([\uAC00-\uD7AF\u3130-\u318F])+/gi.test(text);
|
|
|
|
|
|
export function useInputV2(handleInput: (event: InputEvent) => void) {
|
|
|
- const isComposing = ref(false)
|
|
|
- const handleCompositionStart = () => {
|
|
|
- isComposing.value = true
|
|
|
- }
|
|
|
- const handleCompositionUpdate = (event: any) => {
|
|
|
- const text = event.target.value
|
|
|
- const lastCharacter = text[text.length - 1] || ''
|
|
|
- isComposing.value = !isKorean(lastCharacter)
|
|
|
- }
|
|
|
-
|
|
|
- const handleCompositionEnd = (event: any) => {
|
|
|
- if (isComposing.value) {
|
|
|
- isComposing.value = false
|
|
|
- if (isFunction(handleInput)) {
|
|
|
- handleInput(event)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return {
|
|
|
- handleCompositionStart,
|
|
|
- handleCompositionUpdate,
|
|
|
- handleCompositionEnd,
|
|
|
- isComposing
|
|
|
- }
|
|
|
+ const isComposing = ref(false);
|
|
|
+ const handleCompositionStart = () => {
|
|
|
+ isComposing.value = true;
|
|
|
+ };
|
|
|
+ const handleCompositionUpdate = (event: any) => {
|
|
|
+ const text = event.target.value;
|
|
|
+ const lastCharacter = text[text.length - 1] || "";
|
|
|
+ isComposing.value = !isKorean(lastCharacter);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleCompositionEnd = (event: any) => {
|
|
|
+ if (isComposing.value) {
|
|
|
+ isComposing.value = false;
|
|
|
+ if (isFunction(handleInput)) {
|
|
|
+ handleInput(event);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ return {
|
|
|
+ handleCompositionStart,
|
|
|
+ handleCompositionUpdate,
|
|
|
+ handleCompositionEnd,
|
|
|
+ isComposing,
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
-export declare type CyComboGridOptionsV2 = Readonly<Required<ExtractPropTypes<typeof CyComboGridProps>>>
|
|
|
+export declare type CyComboGridOptionsV2 = Readonly<
|
|
|
+ Required<ExtractPropTypes<typeof CyComboGridProps>>
|
|
|
+>;
|
|
|
|
|
|
-type ValueLabel = { value: string, label: string, [key: string]: any }
|
|
|
+type ValueLabel = { value: string; label: string; [key: string]: any };
|
|
|
|
|
|
-const prefix = ref('cy')
|
|
|
+const prefix = ref("cy");
|
|
|
|
|
|
export default function UesComboGrid(props: CyComboGridOptionsV2, emits: any) {
|
|
|
- const nsSelect = useNamespace('combo-grid', prefix)
|
|
|
- const inputRef = ref<HTMLInputElement | null>(null)
|
|
|
- const tooltipRef = useCompRef(ElTooltip)
|
|
|
- const expanded = ref(false)
|
|
|
- const tableRef = ref<null>(null)
|
|
|
- const calculatorRef = ref<HTMLElement | null>(null)
|
|
|
- const selectionRef = ref<HTMLElement | null>(null)
|
|
|
- const collapseItemRef = ref<HTMLElement | null>(null)
|
|
|
- const detailsTableRaf = ref(null)
|
|
|
- const localSearchData = ref<any[]>([])
|
|
|
- const internalData = isFunction(props.remoteMethod) && typeof props.data === 'undefined'
|
|
|
- const wrapperHeightGoBeyond = ref(false)
|
|
|
-
|
|
|
- const {form, formItem} = useFormItem()
|
|
|
- const {inputId} = useFormItemInputId(props, {
|
|
|
- formItemContext: formItem,
|
|
|
- })
|
|
|
-
|
|
|
- const selectDisabled = computed(() => props.disabled || form?.disabled)
|
|
|
-
|
|
|
- const propsData: WritableComputedRef<any[] | ValueLabel[]> = computed({
|
|
|
- get() {
|
|
|
- return (internalData ? states.data : props.data) as any[] | ValueLabel[]
|
|
|
- },
|
|
|
- set(val: any[]) {
|
|
|
- if (internalData) {
|
|
|
- states.data = val
|
|
|
- } else {
|
|
|
- emits('update:data', val)
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- const dropdownMenuVisible = computed({
|
|
|
- get() {
|
|
|
- return expanded.value
|
|
|
- },
|
|
|
- set(val: boolean) {
|
|
|
- expanded.value = val
|
|
|
- },
|
|
|
- })
|
|
|
-
|
|
|
- const states = reactive({
|
|
|
- menuVisibleOnFocus: false,
|
|
|
- inputValue: '',
|
|
|
- selectedLabel: '',
|
|
|
- inputHovering: false,
|
|
|
- selectionWidth: 0,
|
|
|
- calculatorWidth: 0,
|
|
|
- collapseItemWidth: 0,
|
|
|
- previousQuery: '',
|
|
|
- data: [] as ValueLabel[],
|
|
|
- // 缓存点击的选项
|
|
|
- selected: props.multiple ? ([] as ValueLabel[]) : ({} as any),
|
|
|
- hoveringIndex: -1,
|
|
|
- cacheRow: [] as any[]
|
|
|
- })
|
|
|
-
|
|
|
- const popperRef = computed(() => {
|
|
|
- return tooltipRef.value?.popperRef?.contentRef
|
|
|
- })
|
|
|
-
|
|
|
- const {wrapperRef, isFocused, handleFocus, handleBlur} = useFocusController(
|
|
|
+ const nsSelect = useNamespace("combo-grid", prefix);
|
|
|
+ const inputRef = ref<HTMLInputElement | null>(null);
|
|
|
+ const tooltipRef = useCompRef(ElTooltip);
|
|
|
+ const expanded = ref(false);
|
|
|
+ const tableRef = ref<null>(null);
|
|
|
+ const calculatorRef = ref<HTMLElement | null>(null);
|
|
|
+ const selectionRef = ref<HTMLElement | null>(null);
|
|
|
+ const collapseItemRef = ref<HTMLElement | null>(null);
|
|
|
+ const detailsTableRaf = ref(null);
|
|
|
+ const localSearchData = ref<any[]>([]);
|
|
|
+ const internalData =
|
|
|
+ isFunction(props.remoteMethod) && typeof props.data === "undefined";
|
|
|
+ const wrapperHeightGoBeyond = ref(false);
|
|
|
+
|
|
|
+ const { form, formItem } = useFormItem();
|
|
|
+ const { inputId } = useFormItemInputId(props, {
|
|
|
+ formItemContext: formItem,
|
|
|
+ });
|
|
|
+
|
|
|
+ const selectDisabled = computed(() => props.disabled || form?.disabled);
|
|
|
+
|
|
|
+ const propsData: WritableComputedRef<any[] | ValueLabel[]> = computed({
|
|
|
+ get() {
|
|
|
+ return (internalData ? states.data : props.data) as any[] | ValueLabel[];
|
|
|
+ },
|
|
|
+ set(val: any[]) {
|
|
|
+ if (internalData) {
|
|
|
+ states.data = val;
|
|
|
+ } else {
|
|
|
+ emits("update:data", val);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ const dropdownMenuVisible = computed({
|
|
|
+ get() {
|
|
|
+ return expanded.value;
|
|
|
+ },
|
|
|
+ set(val: boolean) {
|
|
|
+ expanded.value = val;
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ const states = reactive({
|
|
|
+ menuVisibleOnFocus: false,
|
|
|
+ inputValue: "",
|
|
|
+ selectedLabel: "",
|
|
|
+ inputHovering: false,
|
|
|
+ selectionWidth: 0,
|
|
|
+ calculatorWidth: 0,
|
|
|
+ collapseItemWidth: 0,
|
|
|
+ previousQuery: "",
|
|
|
+ data: [] as ValueLabel[],
|
|
|
+ // 缓存点击的选项
|
|
|
+ selected: props.multiple ? ([] as ValueLabel[]) : ({} as any),
|
|
|
+ hoveringIndex: -1,
|
|
|
+ cacheRow: [] as any[],
|
|
|
+ });
|
|
|
+
|
|
|
+ const popperRef = computed(() => {
|
|
|
+ return tooltipRef.value?.popperRef?.contentRef;
|
|
|
+ });
|
|
|
+
|
|
|
+ const { wrapperRef, isFocused, handleFocus, handleBlur } = useFocusController(
|
|
|
+ // @ts-ignore
|
|
|
+ inputRef,
|
|
|
+ {
|
|
|
+ afterFocus() {
|
|
|
+ expanded.value = true;
|
|
|
+ states.menuVisibleOnFocus = true;
|
|
|
+ emits("focus");
|
|
|
+ },
|
|
|
+ beforeBlur(event) {
|
|
|
+ return tooltipRef.value?.isFocusInsideContent(event);
|
|
|
+ },
|
|
|
+ afterBlur() {
|
|
|
+ expanded.value = false;
|
|
|
+ states.menuVisibleOnFocus = false;
|
|
|
+ localSearchData.value = [];
|
|
|
+ formItem?.validate("blur").catch(err => console.warn(err));
|
|
|
+ },
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ function handleClickOutside(event: Event) {
|
|
|
+ expanded.value = false;
|
|
|
+ if (isFocused.value) {
|
|
|
+ const _event = new FocusEvent("focus", event);
|
|
|
+ nextTick().then(r => {
|
|
|
+ handleBlur(_event);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const tableData = computed(() => {
|
|
|
+ return localSearchData.value.length > 0
|
|
|
+ ? localSearchData.value
|
|
|
+ : propsData.value;
|
|
|
+ });
|
|
|
+
|
|
|
+ function localSearch() {
|
|
|
+ localSearchData.value = listFilter(
|
|
|
+ propsData.value,
|
|
|
+ states.inputValue,
|
|
|
+ props.localSearchKey
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleQueryChange(val: string) {
|
|
|
+ if (val === "") {
|
|
|
+ localSearchData.value = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (states.previousQuery === val) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (isComposing.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ states.previousQuery = val;
|
|
|
+ if (isFunction(props.remoteMethod)) {
|
|
|
+ const remoteMethod = props.remoteMethod(val);
|
|
|
+ if (remoteMethod != null && isPromise(remoteMethod)) {
|
|
|
+ remoteMethod.then((data: any) => {
|
|
|
+ propsData.value = data;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 本地搜索
|
|
|
+ localSearch();
|
|
|
+ }
|
|
|
+
|
|
|
+ const onInputChange = () => {
|
|
|
+ if (states.inputValue.length > 0 && !expanded.value) {
|
|
|
+ expanded.value = true;
|
|
|
+ }
|
|
|
+ handleQueryChange(states.inputValue);
|
|
|
+ };
|
|
|
+
|
|
|
+ const onInput = (event: any) => {
|
|
|
+ states.inputValue = event.target.value;
|
|
|
+ states.hoveringIndex = -1;
|
|
|
+ debouncedOnInputChange();
|
|
|
+ };
|
|
|
+
|
|
|
+ const debouncedOnInputChange = XEUtils.debounce(() => {
|
|
|
+ onInputChange();
|
|
|
+ }, props.debounce);
|
|
|
+
|
|
|
+ const {
|
|
|
+ handleCompositionStart,
|
|
|
+ handleCompositionUpdate,
|
|
|
+ handleCompositionEnd,
|
|
|
+ isComposing,
|
|
|
+ } = useInputV2(e => onInput(e));
|
|
|
+
|
|
|
+ const iconReverse = computed(() => {
|
|
|
+ return dropdownMenuVisible.value;
|
|
|
+ });
|
|
|
+
|
|
|
+ const showClear = computed(() => {
|
|
|
+ return props.clearable && hasModelValue.value && states.inputHovering;
|
|
|
+ });
|
|
|
+
|
|
|
+ const bindObj = computed(() => {
|
|
|
+ return (
|
|
|
+ (stringNotBlank(props.value) && stringNotBlank(props.label)) ||
|
|
|
+ stringNotBlank(props.valueLabel)
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ const updateModel = (val: any) => {
|
|
|
+ localSearchData.value = [];
|
|
|
+ states.inputValue = "";
|
|
|
+ const select = {
|
|
|
+ value: val.value,
|
|
|
+ label: val.label,
|
|
|
+ };
|
|
|
+
|
|
|
+ if (props.arrayAdditionallyFields != null) {
|
|
|
+ props.arrayAdditionallyFields.forEach(item => {
|
|
|
// @ts-ignore
|
|
|
- inputRef, {
|
|
|
- afterFocus() {
|
|
|
- expanded.value = true
|
|
|
- states.menuVisibleOnFocus = true
|
|
|
- emits('focus')
|
|
|
- },
|
|
|
- beforeBlur(event) {
|
|
|
- return (tooltipRef.value?.isFocusInsideContent(event))
|
|
|
- },
|
|
|
- afterBlur() {
|
|
|
- expanded.value = false
|
|
|
- states.menuVisibleOnFocus = false
|
|
|
- localSearchData.value = []
|
|
|
- formItem?.validate('blur').catch((err) => console.warn(err))
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- function handleClickOutside(event: Event) {
|
|
|
- expanded.value = false
|
|
|
- if (isFocused.value) {
|
|
|
- const _event = new FocusEvent('focus', event)
|
|
|
- nextTick().then(r => {
|
|
|
- handleBlur(_event)
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const tableData = computed(() => {
|
|
|
- return localSearchData.value.length > 0 ? localSearchData.value : propsData.value;
|
|
|
- })
|
|
|
-
|
|
|
- function localSearch() {
|
|
|
- localSearchData.value = listFilter(propsData.value, states.inputValue, props.localSearchKey)
|
|
|
- }
|
|
|
-
|
|
|
- function handleQueryChange(val: string) {
|
|
|
- if (val === '') {
|
|
|
- localSearchData.value = []
|
|
|
- return;
|
|
|
- }
|
|
|
- if (states.previousQuery === val) {
|
|
|
- return
|
|
|
- }
|
|
|
- if (isComposing.value) {
|
|
|
- return;
|
|
|
- }
|
|
|
- states.previousQuery = val
|
|
|
- if (isFunction(props.remoteMethod)) {
|
|
|
- const remoteMethod = props.remoteMethod(val)
|
|
|
- if (remoteMethod != null && isPromise(remoteMethod)) {
|
|
|
- remoteMethod.then((data: any) => {
|
|
|
- propsData.value = data
|
|
|
- })
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 本地搜索
|
|
|
- localSearch()
|
|
|
- }
|
|
|
-
|
|
|
- const onInputChange = () => {
|
|
|
- if (states.inputValue.length > 0 && !expanded.value) {
|
|
|
- expanded.value = true
|
|
|
- }
|
|
|
- handleQueryChange(states.inputValue)
|
|
|
- }
|
|
|
-
|
|
|
- const onInput = (event: any) => {
|
|
|
- states.inputValue = event.target.value
|
|
|
- states.hoveringIndex = -1
|
|
|
- debouncedOnInputChange()
|
|
|
- }
|
|
|
-
|
|
|
- const debouncedOnInputChange = XEUtils.debounce(() => {
|
|
|
- onInputChange()
|
|
|
- }, props.debounce)
|
|
|
-
|
|
|
- const {
|
|
|
- handleCompositionStart,
|
|
|
- handleCompositionUpdate,
|
|
|
- handleCompositionEnd,
|
|
|
- isComposing
|
|
|
- } = useInputV2((e) => onInput(e))
|
|
|
-
|
|
|
- const iconReverse = computed(() => {
|
|
|
- return dropdownMenuVisible.value
|
|
|
- })
|
|
|
-
|
|
|
- const showClear = computed(() => {
|
|
|
- return props.clearable && hasModelValue.value && states.inputHovering
|
|
|
- })
|
|
|
-
|
|
|
- const bindObj = computed(() => {
|
|
|
- return (stringNotBlank(props.value) && stringNotBlank(props.label)) || stringNotBlank(props.valueLabel)
|
|
|
- })
|
|
|
-
|
|
|
- const updateModel = (val: any) => {
|
|
|
- localSearchData.value = []
|
|
|
- states.inputValue = ''
|
|
|
- const select = {
|
|
|
- value: val.value,
|
|
|
- label: val.label,
|
|
|
- }
|
|
|
-
|
|
|
- if (props.arrayAdditionallyFields != null) {
|
|
|
- props.arrayAdditionallyFields.forEach(item => {
|
|
|
- // @ts-ignore
|
|
|
- select[item] = val[item]
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- if (props.multiple) {
|
|
|
- let index = (props.modelValue as any[]).findIndex(item => {
|
|
|
- return item.value === val.value
|
|
|
- })
|
|
|
- if (index > -1) {
|
|
|
- (props.modelValue as any[]).splice(index, 1)
|
|
|
- states.selected.splice(index, 1)
|
|
|
- } else {
|
|
|
- (props.modelValue as any[]).push(select)
|
|
|
- states.selected.push(select)
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- states.selected = select
|
|
|
- }
|
|
|
-
|
|
|
- if (bindObj.value) {
|
|
|
- // @ts-ignore
|
|
|
- props.modelValue[props.value] = val.value
|
|
|
- // @ts-ignore
|
|
|
- props.modelValue[props.label] = val.label
|
|
|
- states.selectedLabel = val.label
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if (isString(props.modelValue)) {
|
|
|
- emits('update:modelValue', val.value)
|
|
|
- states.selectedLabel = val.label
|
|
|
- return
|
|
|
- }
|
|
|
- if (isNumber(props.modelValue)) {
|
|
|
- emits('update:modelValue', val.value)
|
|
|
- states.selectedLabel = val.label
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const handleClearClick = () => {
|
|
|
-
|
|
|
- function clearFunc() {
|
|
|
- states.selectedLabel = ''
|
|
|
- states.selected = props.multiple ? [] : ({} as any)
|
|
|
- if (props.multiple) {
|
|
|
- emits('update:modelValue', [])
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (bindObj.value) {
|
|
|
- // @ts-ignore
|
|
|
- props.modelValue[props.value] = ''
|
|
|
- // @ts-ignore
|
|
|
- props.modelValue[props.label] = ''
|
|
|
- return;
|
|
|
- }
|
|
|
- if (isString(props.modelValue)) {
|
|
|
- emits('update:modelValue', '')
|
|
|
- return
|
|
|
- }
|
|
|
- if (isNumber(props.modelValue)) {
|
|
|
- emits('update:modelValue', null)
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- clearFunc()
|
|
|
- emits('clear')
|
|
|
- }
|
|
|
-
|
|
|
- const handleTableClick = (val: { row: any, rowIndex: number }) => {
|
|
|
- states.cacheRow.push(val.row)
|
|
|
- states.hoveringIndex = val.rowIndex
|
|
|
- updateModel(val.row)
|
|
|
- if (!props.multiple) {
|
|
|
- toggleMenu()
|
|
|
- }
|
|
|
- emits('rowClick', val)
|
|
|
- }
|
|
|
-
|
|
|
- function toggleMenu() {
|
|
|
- if (props.disabled) return
|
|
|
- if (states.menuVisibleOnFocus) {
|
|
|
- // controlled by automaticDropdown
|
|
|
- states.menuVisibleOnFocus = false
|
|
|
- } else {
|
|
|
- expanded.value = !expanded.value
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const getGapWidth = () => {
|
|
|
- if (!selectionRef.value) return 0
|
|
|
- const style = window.getComputedStyle(selectionRef.value)
|
|
|
- return Number.parseFloat(style.gap || '6px')
|
|
|
- }
|
|
|
-
|
|
|
- const inputStyle = computed(() => ({
|
|
|
- width: `${Math.max(states.calculatorWidth, 11)}px`
|
|
|
- }))
|
|
|
-
|
|
|
- const collapseTagStyle = computed(() => {
|
|
|
- return {maxWidth: `${states.selectionWidth}px`}
|
|
|
- })
|
|
|
-
|
|
|
- // computed style
|
|
|
- const tagStyle = computed(() => {
|
|
|
- const gapWidth = getGapWidth()
|
|
|
- const maxWidth =
|
|
|
- collapseItemRef.value && props.maxCollapseTags === 1
|
|
|
- ? states.selectionWidth - states.collapseItemWidth - gapWidth
|
|
|
- : states.selectionWidth
|
|
|
- return {maxWidth: `${maxWidth - 20}px`}
|
|
|
- })
|
|
|
-
|
|
|
- const hasModelValue = computed(() => {
|
|
|
- if (isString(props.modelValue) && stringNotBlank(props.modelValue)) {
|
|
|
- return true
|
|
|
- }
|
|
|
- if (isNumber(props.modelValue) && stringNotBlank(props.modelValue)) {
|
|
|
- return true
|
|
|
- }
|
|
|
- // @ts-ignore
|
|
|
- if (bindObj.value && stringNotBlank(props.modelValue[props!.value])) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return isArray(props.modelValue) && props.modelValue.length > 0;
|
|
|
- })
|
|
|
-
|
|
|
- const shouldShowPlaceholder = computed(() => {
|
|
|
- return !states.inputValue
|
|
|
- })
|
|
|
-
|
|
|
- const currentPlaceholder = computed(() => {
|
|
|
- if (props.multiple) {
|
|
|
- return (props.modelValue as any[]).length > 0 ? '' : props.placeholder;
|
|
|
- }
|
|
|
- return states.selectedLabel || props.placeholder
|
|
|
- })
|
|
|
-
|
|
|
-
|
|
|
- const isTransparent = computed(() => {
|
|
|
- return !hasModelValue.value || (expanded.value && !states.inputValue)
|
|
|
- })
|
|
|
-
|
|
|
- const showTagList = computed(() => {
|
|
|
- if (props.multiple) {
|
|
|
- const temp = states.selected.length > 0 ? [states.selected[0]] : []
|
|
|
- return props.collapseTags ? temp : states.selected
|
|
|
- }
|
|
|
- return []
|
|
|
- })
|
|
|
-
|
|
|
- const deleteTag = (item: any, index: number) => {
|
|
|
- (props.modelValue as ValueLabel[]).splice(index, 1)
|
|
|
- states.selected.splice(index, 1)
|
|
|
- }
|
|
|
-
|
|
|
- function getObjValue(): string {
|
|
|
+ select[item] = val[item];
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (props.multiple) {
|
|
|
+ let index = (props.modelValue as any[]).findIndex(item => {
|
|
|
+ return item.value === val.value;
|
|
|
+ });
|
|
|
+ if (index > -1) {
|
|
|
+ (props.modelValue as any[]).splice(index, 1);
|
|
|
+ states.selected.splice(index, 1);
|
|
|
+ } else {
|
|
|
+ (props.modelValue as any[]).push(select);
|
|
|
+ states.selected.push(select);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ states.selected = select;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bindObj.value) {
|
|
|
+ // @ts-ignore
|
|
|
+ props.modelValue[props.value] = val.value;
|
|
|
+ // @ts-ignore
|
|
|
+ props.modelValue[props.label] = val.label;
|
|
|
+ states.selectedLabel = val.label;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isString(props.modelValue)) {
|
|
|
+ emits("update:modelValue", val.value);
|
|
|
+ states.selectedLabel = val.label;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (isNumber(props.modelValue)) {
|
|
|
+ emits("update:modelValue", val.value);
|
|
|
+ states.selectedLabel = val.label;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleClearClick = () => {
|
|
|
+ function clearFunc() {
|
|
|
+ states.selectedLabel = "";
|
|
|
+ states.selected = props.multiple ? [] : ({} as any);
|
|
|
+ if (props.multiple) {
|
|
|
+ emits("update:modelValue", []);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bindObj.value) {
|
|
|
// @ts-ignore
|
|
|
- return props.modelValue[props.value]
|
|
|
- }
|
|
|
-
|
|
|
- function getObjLabel(): string {
|
|
|
+ props.modelValue[props.value] = "";
|
|
|
// @ts-ignore
|
|
|
- return props.modelValue[props.label]
|
|
|
- }
|
|
|
-
|
|
|
- function getModelArr() {
|
|
|
- return (props.modelValue as ValueLabel[])
|
|
|
- }
|
|
|
-
|
|
|
- function handleObj() {
|
|
|
- states.selected = {
|
|
|
- value: getObjValue(),
|
|
|
- label: getObjLabel(),
|
|
|
- }
|
|
|
- states.selectedLabel = getObjLabel()
|
|
|
- }
|
|
|
-
|
|
|
- function handleSelect() {
|
|
|
- if (props.modelValue === states.selected.value) {
|
|
|
- states.selectedLabel = states.selected.label
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- let data: any[]
|
|
|
-
|
|
|
- data = filter(states.cacheRow, (item) => {
|
|
|
- return item.value === props.modelValue
|
|
|
- })
|
|
|
-
|
|
|
- if (data.length === 0) {
|
|
|
- data = filter(propsData.value, (item) => {
|
|
|
- return item.value === props.modelValue
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- if (data.length > 0) {
|
|
|
- states.selected = {
|
|
|
- value: data[0].value,
|
|
|
- label: data[0].label,
|
|
|
- }
|
|
|
- states.selectedLabel = states.selected.label
|
|
|
- return
|
|
|
- }
|
|
|
- states.selectedLabel = XEUtils.toString(props.modelValue)
|
|
|
- }
|
|
|
-
|
|
|
- function handleMultiple() {
|
|
|
- states.selected = XEUtils.clone(getModelArr(), true)
|
|
|
- }
|
|
|
-
|
|
|
- function handleChangeModel() {
|
|
|
- if (bindObj.value) {
|
|
|
- handleObj()
|
|
|
- } else if (props.multiple) {
|
|
|
- handleMultiple()
|
|
|
+ props.modelValue[props.label] = "";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (isString(props.modelValue)) {
|
|
|
+ emits("update:modelValue", "");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (isNumber(props.modelValue)) {
|
|
|
+ emits("update:modelValue", null);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ clearFunc();
|
|
|
+ emits("clear");
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleTableClick = (val: { row: any; rowIndex: number }) => {
|
|
|
+ states.cacheRow.push(val.row);
|
|
|
+ states.hoveringIndex = val.rowIndex;
|
|
|
+ updateModel(val.row);
|
|
|
+ if (!props.multiple) {
|
|
|
+ toggleMenu();
|
|
|
+ }
|
|
|
+ emits("rowClick", val);
|
|
|
+ };
|
|
|
+
|
|
|
+ function toggleMenu() {
|
|
|
+ if (props.disabled) return;
|
|
|
+ if (states.menuVisibleOnFocus) {
|
|
|
+ // controlled by automaticDropdown
|
|
|
+ states.menuVisibleOnFocus = false;
|
|
|
+ } else {
|
|
|
+ expanded.value = !expanded.value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const getGapWidth = () => {
|
|
|
+ if (!selectionRef.value) return 0;
|
|
|
+ const style = window.getComputedStyle(selectionRef.value);
|
|
|
+ return Number.parseFloat(style.gap || "6px");
|
|
|
+ };
|
|
|
+
|
|
|
+ const inputStyle = computed(() => ({
|
|
|
+ width: `${Math.max(states.calculatorWidth, 11)}px`,
|
|
|
+ }));
|
|
|
+
|
|
|
+ const collapseTagStyle = computed(() => {
|
|
|
+ return { maxWidth: `${states.selectionWidth}px` };
|
|
|
+ });
|
|
|
+
|
|
|
+ // computed style
|
|
|
+ const tagStyle = computed(() => {
|
|
|
+ const gapWidth = getGapWidth();
|
|
|
+ const maxWidth =
|
|
|
+ collapseItemRef.value && props.maxCollapseTags === 1
|
|
|
+ ? states.selectionWidth - states.collapseItemWidth - gapWidth
|
|
|
+ : states.selectionWidth;
|
|
|
+ return { maxWidth: `${maxWidth - 20}px` };
|
|
|
+ });
|
|
|
+
|
|
|
+ const hasModelValue = computed(() => {
|
|
|
+ if (isString(props.modelValue) && stringNotBlank(props.modelValue)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (isNumber(props.modelValue) && stringNotBlank(props.modelValue)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ // @ts-ignore
|
|
|
+ if (bindObj.value && stringNotBlank(props.modelValue[props!.value])) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return isArray(props.modelValue) && props.modelValue.length > 0;
|
|
|
+ });
|
|
|
+
|
|
|
+ const shouldShowPlaceholder = computed(() => {
|
|
|
+ return !states.inputValue;
|
|
|
+ });
|
|
|
+
|
|
|
+ const currentPlaceholder = computed(() => {
|
|
|
+ if (props.multiple) {
|
|
|
+ return (props.modelValue as any[]).length > 0 ? "" : props.placeholder;
|
|
|
+ }
|
|
|
+ return states.selectedLabel || props.placeholder;
|
|
|
+ });
|
|
|
+
|
|
|
+ const isTransparent = computed(() => {
|
|
|
+ return !hasModelValue.value || (expanded.value && !states.inputValue);
|
|
|
+ });
|
|
|
+
|
|
|
+ const showTagList = computed(() => {
|
|
|
+ if (props.multiple) {
|
|
|
+ const temp = states.selected.length > 0 ? [states.selected[0]] : [];
|
|
|
+ return props.collapseTags ? temp : states.selected;
|
|
|
+ }
|
|
|
+ return [];
|
|
|
+ });
|
|
|
+
|
|
|
+ const deleteTag = (item: any, index: number) => {
|
|
|
+ (props.modelValue as ValueLabel[]).splice(index, 1);
|
|
|
+ states.selected.splice(index, 1);
|
|
|
+ };
|
|
|
+
|
|
|
+ function getObjValue(): string {
|
|
|
+ // @ts-ignore
|
|
|
+ return props.modelValue[props.value];
|
|
|
+ }
|
|
|
+
|
|
|
+ function getObjLabel(): string {
|
|
|
+ // @ts-ignore
|
|
|
+ return props.modelValue[props.label];
|
|
|
+ }
|
|
|
+
|
|
|
+ function getModelArr() {
|
|
|
+ return props.modelValue as ValueLabel[];
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleObj() {
|
|
|
+ states.selected = {
|
|
|
+ value: getObjValue(),
|
|
|
+ label: getObjLabel(),
|
|
|
+ };
|
|
|
+ states.selectedLabel = getObjLabel();
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleSelect() {
|
|
|
+ if (props.modelValue === states.selected.value) {
|
|
|
+ states.selectedLabel = states.selected.label;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let data: any[];
|
|
|
+
|
|
|
+ data = filter(states.cacheRow, item => {
|
|
|
+ return item.value === props.modelValue;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (data.length === 0) {
|
|
|
+ data = filter(propsData.value, item => {
|
|
|
+ return item.value === props.modelValue;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.length > 0) {
|
|
|
+ states.selected = {
|
|
|
+ value: data[0].value,
|
|
|
+ label: data[0].label,
|
|
|
+ };
|
|
|
+ states.selectedLabel = states.selected.label;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ states.selectedLabel = XEUtils.toString(props.modelValue);
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleMultiple() {
|
|
|
+ states.selected = XEUtils.clone(getModelArr(), true);
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleChangeModel() {
|
|
|
+ if (bindObj.value) {
|
|
|
+ handleObj();
|
|
|
+ } else if (props.multiple) {
|
|
|
+ handleMultiple();
|
|
|
+ } else {
|
|
|
+ handleSelect();
|
|
|
+ }
|
|
|
+ if (!expanded.value) {
|
|
|
+ states.inputValue = states.selectedLabel;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => props.modelValue,
|
|
|
+ (val, oldVal) => {
|
|
|
+ handleChangeModel();
|
|
|
+ if (!isEqual(val, oldVal)) {
|
|
|
+ formItem?.validate("change").catch(err => console.error(err));
|
|
|
+ }
|
|
|
+ emits("change", props.modelValue);
|
|
|
+ },
|
|
|
+ {
|
|
|
+ flush: "post",
|
|
|
+ deep: true,
|
|
|
+ immediate: true,
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => expanded.value,
|
|
|
+ val => {
|
|
|
+ if (val) {
|
|
|
+ states.inputValue = "";
|
|
|
+ handleQueryChange(states.inputValue);
|
|
|
+ } else {
|
|
|
+ if (bindObj.value || props.multiple) {
|
|
|
+ states.inputValue = "";
|
|
|
} else {
|
|
|
- handleSelect()
|
|
|
- }
|
|
|
- if (!expanded.value) {
|
|
|
- states.inputValue = states.selectedLabel
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- watch(
|
|
|
- () => props.modelValue,
|
|
|
- (val, oldVal) => {
|
|
|
- handleChangeModel()
|
|
|
- if (!isEqual(val, oldVal)) {
|
|
|
- formItem?.validate('change').catch((err) => console.error(err))
|
|
|
- }
|
|
|
- emits('change', props.modelValue)
|
|
|
- }, {
|
|
|
- flush: 'post',
|
|
|
- deep: true,
|
|
|
- immediate: true
|
|
|
- }
|
|
|
- )
|
|
|
-
|
|
|
- watch(
|
|
|
- () => expanded.value,
|
|
|
- (val) => {
|
|
|
- if (val) {
|
|
|
- states.inputValue = ''
|
|
|
- handleQueryChange(states.inputValue)
|
|
|
- } else {
|
|
|
- if (bindObj.value || props.multiple) {
|
|
|
- states.inputValue = ''
|
|
|
- } else {
|
|
|
- states.inputValue = states.selectedLabel
|
|
|
- }
|
|
|
- states.previousQuery = ''
|
|
|
- }
|
|
|
- emits('visible-change', val)
|
|
|
- }
|
|
|
- )
|
|
|
-
|
|
|
- watch(
|
|
|
- () => propsData.value,
|
|
|
- () => {
|
|
|
- states.hoveringIndex = -1
|
|
|
- handleChangeModel()
|
|
|
- }, {
|
|
|
- flush: 'post',
|
|
|
- deep: true,
|
|
|
- }
|
|
|
- )
|
|
|
-
|
|
|
- const resetCalculatorWidth = () => {
|
|
|
- states.calculatorWidth = calculatorRef.value!.getBoundingClientRect().width
|
|
|
- }
|
|
|
-
|
|
|
- const updateTooltip = () => {
|
|
|
- tooltipRef.value?.updatePopper?.()
|
|
|
- }
|
|
|
-
|
|
|
- const resetSelectionWidth = () => {
|
|
|
- states.selectionWidth = selectionRef.value!.getBoundingClientRect().width
|
|
|
- }
|
|
|
-
|
|
|
- const resetCollapseItemWidth = () => {
|
|
|
- states.collapseItemWidth =
|
|
|
- collapseItemRef.value!.getBoundingClientRect().width
|
|
|
- }
|
|
|
-
|
|
|
- function columnsTableSortable() {
|
|
|
- const el = (detailsTableRaf.value!['$el'] as HTMLDivElement).querySelector('.vxe-table--body tbody')
|
|
|
- const ops = {
|
|
|
- handle: '.vxe-body--row',
|
|
|
- onEnd: function ({newIndex, oldIndex}: { newIndex: number, oldIndex: number }) {
|
|
|
- const currRow = getModelArr().splice(oldIndex, 1)[0];
|
|
|
- getModelArr().splice(newIndex, 0, currRow);
|
|
|
-
|
|
|
- const currRow2 = states.selected.splice(oldIndex, 1)[0];
|
|
|
- states.selected.splice(newIndex, 0, currRow2);
|
|
|
- }
|
|
|
- }
|
|
|
- Sortable.create(el, ops)
|
|
|
- }
|
|
|
-
|
|
|
- useResizeObserver(calculatorRef, resetCalculatorWidth)
|
|
|
- useResizeObserver(wrapperRef, () => {
|
|
|
- updateTooltip()
|
|
|
- wrapperHeightGoBeyond.value = wrapperRef.value!.getBoundingClientRect().height > 28
|
|
|
- })
|
|
|
- useResizeObserver(selectionRef, resetSelectionWidth)
|
|
|
- useResizeObserver(collapseItemRef, resetCollapseItemWidth)
|
|
|
-
|
|
|
+ states.inputValue = states.selectedLabel;
|
|
|
+ }
|
|
|
+ states.previousQuery = "";
|
|
|
+ }
|
|
|
+ emits("visible-change", val);
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => propsData.value,
|
|
|
+ () => {
|
|
|
+ states.hoveringIndex = -1;
|
|
|
+ handleChangeModel();
|
|
|
+ },
|
|
|
+ {
|
|
|
+ flush: "post",
|
|
|
+ deep: true,
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ const resetCalculatorWidth = () => {
|
|
|
+ states.calculatorWidth = calculatorRef.value!.getBoundingClientRect().width;
|
|
|
+ };
|
|
|
+
|
|
|
+ const updateTooltip = () => {
|
|
|
+ tooltipRef.value?.updatePopper?.();
|
|
|
+ };
|
|
|
+
|
|
|
+ const resetSelectionWidth = () => {
|
|
|
+ states.selectionWidth = selectionRef.value!.getBoundingClientRect().width;
|
|
|
+ };
|
|
|
+
|
|
|
+ const resetCollapseItemWidth = () => {
|
|
|
+ states.collapseItemWidth =
|
|
|
+ collapseItemRef.value!.getBoundingClientRect().width;
|
|
|
+ };
|
|
|
+
|
|
|
+ function columnsTableSortable() {
|
|
|
+ const el = (detailsTableRaf.value!["$el"] as HTMLDivElement).querySelector(
|
|
|
+ ".vxe-table--body tbody"
|
|
|
+ );
|
|
|
+ const ops = {
|
|
|
+ handle: ".vxe-body--row",
|
|
|
+ onEnd: function ({
|
|
|
+ newIndex,
|
|
|
+ oldIndex,
|
|
|
+ }: {
|
|
|
+ newIndex: number;
|
|
|
+ oldIndex: number;
|
|
|
+ }) {
|
|
|
+ const currRow = getModelArr().splice(oldIndex, 1)[0];
|
|
|
+ getModelArr().splice(newIndex, 0, currRow);
|
|
|
+
|
|
|
+ const currRow2 = states.selected.splice(oldIndex, 1)[0];
|
|
|
+ states.selected.splice(newIndex, 0, currRow2);
|
|
|
+ },
|
|
|
+ };
|
|
|
+ Sortable.create(el, ops);
|
|
|
+ }
|
|
|
+
|
|
|
+ useResizeObserver(calculatorRef, resetCalculatorWidth);
|
|
|
+ useResizeObserver(wrapperRef, () => {
|
|
|
+ updateTooltip();
|
|
|
+ wrapperHeightGoBeyond.value =
|
|
|
+ wrapperRef.value!.getBoundingClientRect().height > 28;
|
|
|
+ });
|
|
|
+ useResizeObserver(selectionRef, resetSelectionWidth);
|
|
|
+ useResizeObserver(collapseItemRef, resetCollapseItemWidth);
|
|
|
+
|
|
|
+ // 键盘事件
|
|
|
+ function navigateOptions(direction: "next" | "prev") {
|
|
|
+ if (!expanded.value) {
|
|
|
+ expanded.value = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (tableData.value.length === 0) return;
|
|
|
+ if (direction === "next") {
|
|
|
+ states.hoveringIndex++;
|
|
|
+ if (states.hoveringIndex === tableData.value.length) {
|
|
|
+ states.hoveringIndex = 0;
|
|
|
+ }
|
|
|
+ } else if (direction === "prev") {
|
|
|
+ states.hoveringIndex--;
|
|
|
+ if (states.hoveringIndex < 0) {
|
|
|
+ states.hoveringIndex = tableData.value.length - 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const selectData = tableData.value[states.hoveringIndex];
|
|
|
+ tableRef.value?.setCurrentRow(selectData);
|
|
|
+ tableRef.value?.scrollToRow(selectData);
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleEsc(event: KeyboardEvent) {
|
|
|
+ function handleStop() {
|
|
|
+ event.stopPropagation();
|
|
|
+ event.preventDefault();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (states.inputValue.length > 0) {
|
|
|
+ states.inputValue = "";
|
|
|
+ handleStop();
|
|
|
+ } else {
|
|
|
+ if (expanded.value) {
|
|
|
+ handleStop();
|
|
|
+ }
|
|
|
+ expanded.value = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function selectOption() {
|
|
|
+ if (!expanded.value) {
|
|
|
+ toggleMenu();
|
|
|
+ } else {
|
|
|
+ if (tableData.value[states.hoveringIndex]) {
|
|
|
+ handleTableClick({
|
|
|
+ row: tableData.value[states.hoveringIndex],
|
|
|
+ rowIndex: states.hoveringIndex,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function deletePrevTag(e: KeyboardEvent & InputEvent) {
|
|
|
+ if (!props.multiple) return;
|
|
|
+ if (e.code === "Delete") return;
|
|
|
+ // @ts-ignore
|
|
|
+ if (e.target.value.length <= 0) {
|
|
|
+ const length = showTagList.value.length;
|
|
|
+ if (length === 0) return;
|
|
|
+ deleteTag(showTagList.value[length], length - 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function rowClass({ row }: { row: any }) {
|
|
|
+ const value = row.value;
|
|
|
+ if (props.multiple) {
|
|
|
+ for (let i = 0; i < getModelArr().length; i++) {
|
|
|
+ const item = getModelArr()[i];
|
|
|
+ if (item.value === value) {
|
|
|
+ return "cy-combo-grid__table_key";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (bindObj.value) {
|
|
|
+ if (getObjValue() === value) {
|
|
|
+ return "cy-combo-grid__table_key";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (props.modelValue === value) {
|
|
|
+ return "cy-combo-grid__table_key";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ if (props.multiple) {
|
|
|
+ if (!isArray(props.modelValue)) {
|
|
|
+ emits("update:modelValue", []);
|
|
|
+ }
|
|
|
+ props.sortable && columnsTableSortable();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ inputId,
|
|
|
+ nsSelect,
|
|
|
+ handleFocus,
|
|
|
+ inputRef,
|
|
|
+ handleBlur,
|
|
|
+ isFocused,
|
|
|
+ handleClickOutside,
|
|
|
+ tooltipRef,
|
|
|
+ popperRef,
|
|
|
+ dropdownMenuVisible,
|
|
|
+ tableRef,
|
|
|
+ states,
|
|
|
+ onInput,
|
|
|
+ handleCompositionStart,
|
|
|
+ handleCompositionUpdate,
|
|
|
+ handleCompositionEnd,
|
|
|
+ toggleMenu,
|
|
|
+ iconReverse,
|
|
|
+ showClear,
|
|
|
+ handleClearClick,
|
|
|
+ handleTableClick,
|
|
|
+ wrapperRef,
|
|
|
+ currentPlaceholder,
|
|
|
+ calculatorRef,
|
|
|
+ shouldShowPlaceholder,
|
|
|
+ isTransparent,
|
|
|
+ selectionRef,
|
|
|
+ collapseItemRef,
|
|
|
+ deleteTag,
|
|
|
+ showTagList,
|
|
|
+ detailsTableRaf,
|
|
|
+ tableData,
|
|
|
+ wrapperHeightGoBeyond,
|
|
|
+ selectDisabled,
|
|
|
|
|
|
// 键盘事件
|
|
|
- function navigateOptions(direction: 'next' | 'prev') {
|
|
|
- if (!expanded.value) {
|
|
|
- expanded.value = true
|
|
|
- return
|
|
|
- }
|
|
|
- if (tableData.value.length === 0) return;
|
|
|
- if (direction === 'next') {
|
|
|
- states.hoveringIndex++
|
|
|
- if (states.hoveringIndex === tableData.value.length) {
|
|
|
- states.hoveringIndex = 0
|
|
|
- }
|
|
|
- } else if (direction === 'prev') {
|
|
|
- states.hoveringIndex--
|
|
|
- if (states.hoveringIndex < 0) {
|
|
|
- states.hoveringIndex = tableData.value.length - 1
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const selectData = tableData.value[states.hoveringIndex]
|
|
|
- tableRef.value?.setCurrentRow(selectData);
|
|
|
- tableRef.value?.scrollToRow(selectData)
|
|
|
- }
|
|
|
-
|
|
|
- function handleEsc(event: KeyboardEvent) {
|
|
|
-
|
|
|
- function handleStop() {
|
|
|
- event.stopPropagation();
|
|
|
- event.preventDefault();
|
|
|
- }
|
|
|
-
|
|
|
- if (states.inputValue.length > 0) {
|
|
|
- states.inputValue = ''
|
|
|
- handleStop()
|
|
|
- } else {
|
|
|
- if (expanded.value) {
|
|
|
- handleStop()
|
|
|
- }
|
|
|
- expanded.value = false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function selectOption() {
|
|
|
- if (!expanded.value) {
|
|
|
- toggleMenu()
|
|
|
- } else {
|
|
|
- if (tableData.value[states.hoveringIndex]) {
|
|
|
- handleTableClick({row: tableData.value[states.hoveringIndex], rowIndex: states.hoveringIndex})
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function deletePrevTag(e: KeyboardEvent & InputEvent) {
|
|
|
- if (!props.multiple) return
|
|
|
- if (e.code === 'Delete') return
|
|
|
- // @ts-ignore
|
|
|
- if (e.target.value.length <= 0) {
|
|
|
- const length = showTagList.value.length
|
|
|
- if (length === 0) return
|
|
|
- deleteTag(showTagList.value[length], length - 1)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function rowClass({row}: { row: any }) {
|
|
|
- const value = row.value
|
|
|
- if (props.multiple) {
|
|
|
- for (let i = 0; i < getModelArr().length; i++) {
|
|
|
- const item = getModelArr()[i]
|
|
|
- if (item.value === value) {
|
|
|
- return 'cy-combo-grid__table_key'
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (bindObj.value) {
|
|
|
- if (getObjValue() === value) {
|
|
|
- return 'cy-combo-grid__table_key'
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (props.modelValue === value) {
|
|
|
- return 'cy-combo-grid__table_key'
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- onMounted(() => {
|
|
|
- if (props.multiple) {
|
|
|
- if (!isArray(props.modelValue)) {
|
|
|
- emits('update:modelValue', [])
|
|
|
- }
|
|
|
- props.sortable && columnsTableSortable()
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- return {
|
|
|
- inputId,
|
|
|
- nsSelect,
|
|
|
- handleFocus,
|
|
|
- inputRef,
|
|
|
- handleBlur,
|
|
|
- isFocused,
|
|
|
- handleClickOutside,
|
|
|
- tooltipRef,
|
|
|
- popperRef,
|
|
|
- dropdownMenuVisible,
|
|
|
- tableRef,
|
|
|
- states,
|
|
|
- onInput,
|
|
|
- handleCompositionStart,
|
|
|
- handleCompositionUpdate,
|
|
|
- handleCompositionEnd,
|
|
|
- toggleMenu,
|
|
|
- iconReverse,
|
|
|
- showClear,
|
|
|
- handleClearClick,
|
|
|
- handleTableClick,
|
|
|
- wrapperRef,
|
|
|
- currentPlaceholder,
|
|
|
- calculatorRef,
|
|
|
- shouldShowPlaceholder,
|
|
|
- isTransparent,
|
|
|
- selectionRef,
|
|
|
- collapseItemRef,
|
|
|
- deleteTag,
|
|
|
- showTagList,
|
|
|
- detailsTableRaf,
|
|
|
- tableData,
|
|
|
- wrapperHeightGoBeyond,
|
|
|
- selectDisabled,
|
|
|
-
|
|
|
- // 键盘事件
|
|
|
- navigateOptions,
|
|
|
- handleEsc,
|
|
|
- selectOption,
|
|
|
- deletePrevTag,
|
|
|
-
|
|
|
- inputStyle,
|
|
|
- tagStyle,
|
|
|
- collapseTagStyle,
|
|
|
- rowClass,
|
|
|
- }
|
|
|
+ navigateOptions,
|
|
|
+ handleEsc,
|
|
|
+ selectOption,
|
|
|
+ deletePrevTag,
|
|
|
+
|
|
|
+ inputStyle,
|
|
|
+ tagStyle,
|
|
|
+ collapseTagStyle,
|
|
|
+ rowClass,
|
|
|
+ };
|
|
|
}
|
|
|
-
|