r-util-js/packages/uview-plus/src/picker/index.ts

124 lines
3.2 KiB
TypeScript

import { isEqual } from "lodash-es";
import { toRef, computed, watch } from "vue";
import type { Ref } from "vue";
interface UsePickerOptions {
/** 选中的值 */
value?: unknown[] | Ref<unknown[]>;
show?: boolean | Ref<boolean>;
/** 选中的值 */
indexes?: Array<number | null> | Ref<Array<number | null>>;
columns?: UViewPlus.PickerColumns | Ref<UViewPlus.PickerColumns>;
textName?: string;
valueName?: string;
placeholder?: string;
separator?: string;
}
/**
* 多列 picker
* @param options 选项
* @returns
*/
export function usePicker(options: UsePickerOptions) {
const value = toRef(options.value ?? []);
const show = toRef(options.show ?? false);
const indexes = toRef(options.indexes ?? []);
const columns = toRef(options.columns ?? [[]]);
const textName = toRef(options.textName ?? "text");
const valueName = toRef(options.valueName ?? "value");
const placeholder = toRef(options.placeholder ?? "请选择");
const separator = toRef(options.separator ?? " ");
const text = computed(() => {
const textArray = indexes.value.map((i, index) => {
if (i == null) return null;
const item = columns.value[index][i];
return item?.[textName.value] ?? null;
});
if (textArray.some((v) => v == null)) {
return placeholder.value;
}
return textArray.join(separator.value);
});
// 监听 indexes 变化,更新 value
watch(
[indexes, columns],
([newIndexes, newColumns]) => {
console.log("indexes changed:", newIndexes, newColumns);
if (!newIndexes.length) return;
const newValue = newIndexes.map((index, columnIndex) => {
if (index == null) return null;
const item = newColumns[columnIndex]?.[index];
return item?.[valueName.value] ?? null;
});
if (!isEqual(newValue, value.value)) {
value.value = newValue;
}
},
{ immediate: true, deep: true },
);
// 监听 value 变化,更新 indexes
watch(
[value, columns],
([newValue, newColumns]) => {
console.log("value changed:", newValue, newColumns);
const newIndexes = newColumns.map((column, columnIndex) => {
const index = column.findIndex(
(item) => item[valueName.value] === newValue?.[columnIndex],
);
return index >= 0 ? index : null;
});
if (!isEqual(newIndexes, indexes.value)) {
indexes.value = newIndexes;
}
},
{ immediate: true, deep: true },
);
function handleConfirm(e: UViewPlus.PickerConfirmEvent) {
console.log("handleConfirm:", e);
indexes.value = e.indexs;
}
function columnValueToText(v: unknown, colIndex = 0) {
const currentItem = columns.value[colIndex].find(
(item) => item[valueName.value] === v,
);
return currentItem?.[textName.value];
}
function valueToText(v: unknown[]) {
return v.map((item, index) => columnValueToText(item, index));
}
function showPicker() {
show.value = true;
}
function hidePicker() {
show.value = false;
}
return {
text,
value,
indexes,
columns,
handleConfirm,
valueToText,
columnValueToText,
textName,
valueName,
show,
showPicker,
hidePicker,
};
}