mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-10-09 03:16:37 +08:00
Compare commits
No commits in common. "87adc35f2e2fbe10238ef9eb415842f5ef81b916" and "8a7cd5934b01ec884c1085048b01fc7513262d32" have entirely different histories.
87adc35f2e
...
8a7cd5934b
@ -6,4 +6,6 @@ import useSvgIconRender from './use-svg-icon-render';
|
|||||||
import useTable from './use-table';
|
import useTable from './use-table';
|
||||||
|
|
||||||
export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useTable };
|
export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useTable };
|
||||||
|
|
||||||
|
export * from './use-signal';
|
||||||
export type * from './use-table';
|
export type * from './use-table';
|
||||||
|
144
packages/hooks/src/use-signal.ts
Normal file
144
packages/hooks/src/use-signal.ts
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import { computed, ref, shallowRef, triggerRef } from 'vue';
|
||||||
|
import type {
|
||||||
|
ComputedGetter,
|
||||||
|
DebuggerOptions,
|
||||||
|
Ref,
|
||||||
|
ShallowRef,
|
||||||
|
WritableComputedOptions,
|
||||||
|
WritableComputedRef
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
type Updater<T> = (value: T) => T;
|
||||||
|
type Mutator<T> = (value: T) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal is a reactive value that can be set, updated or mutated
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const count = useSignal(0);
|
||||||
|
*
|
||||||
|
* // `watchEffect`
|
||||||
|
* watchEffect(() => {
|
||||||
|
* console.log(count());
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // watch
|
||||||
|
* watch(count, value => {
|
||||||
|
* console.log(value);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // useComputed
|
||||||
|
* const double = useComputed(() => count() * 2);
|
||||||
|
* const writeableDouble = useComputed({
|
||||||
|
* get: () => count() * 2,
|
||||||
|
* set: value => count.set(value / 2)
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface Signal<T> {
|
||||||
|
(): Readonly<T>;
|
||||||
|
/**
|
||||||
|
* Set the value of the signal
|
||||||
|
*
|
||||||
|
* It recommend use `set` for primitive values
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
set(value: T): void;
|
||||||
|
/**
|
||||||
|
* Update the value of the signal using an updater function
|
||||||
|
*
|
||||||
|
* It recommend use `update` for non-primitive values, only the first level of the object will be reactive.
|
||||||
|
*
|
||||||
|
* @param updater
|
||||||
|
*/
|
||||||
|
update(updater: Updater<T>): void;
|
||||||
|
/**
|
||||||
|
* Mutate the value of the signal using a mutator function
|
||||||
|
*
|
||||||
|
* this action will call `triggerRef`, so the value will be tracked on `watchEffect`.
|
||||||
|
*
|
||||||
|
* It recommend use `mutate` for non-primitive values, all levels of the object will be reactive.
|
||||||
|
*
|
||||||
|
* @param mutator
|
||||||
|
*/
|
||||||
|
mutate(mutator: Mutator<T>): void;
|
||||||
|
/**
|
||||||
|
* Get the reference of the signal
|
||||||
|
*
|
||||||
|
* Sometimes it can be useful to make `v-model` work with the signal
|
||||||
|
*
|
||||||
|
* ```vue
|
||||||
|
* <template>
|
||||||
|
* <input v-model="model.count" />
|
||||||
|
* </template>;
|
||||||
|
*
|
||||||
|
* <script setup lang="ts">
|
||||||
|
* const state = useSignal({ count: 0 }, { useRef: true });
|
||||||
|
*
|
||||||
|
* const model = state.getRef();
|
||||||
|
* </script>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
getRef(): Readonly<ShallowRef<Readonly<T>>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReadonlySignal<T> {
|
||||||
|
(): Readonly<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SignalOptions {
|
||||||
|
/**
|
||||||
|
* Whether to use `ref` to store the value
|
||||||
|
*
|
||||||
|
* @default false use `sharedRef` to store the value
|
||||||
|
*/
|
||||||
|
useRef?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSignal<T>(initialValue: T, options?: SignalOptions): Signal<T> {
|
||||||
|
const { useRef } = options || {};
|
||||||
|
|
||||||
|
const state = useRef ? (ref(initialValue) as Ref<T>) : shallowRef(initialValue);
|
||||||
|
|
||||||
|
return createSignal(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useComputed<T>(getter: ComputedGetter<T>, debugOptions?: DebuggerOptions): ReadonlySignal<T>;
|
||||||
|
export function useComputed<T>(options: WritableComputedOptions<T>, debugOptions?: DebuggerOptions): Signal<T>;
|
||||||
|
export function useComputed<T>(
|
||||||
|
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>,
|
||||||
|
debugOptions?: DebuggerOptions
|
||||||
|
) {
|
||||||
|
const isGetter = typeof getterOrOptions === 'function';
|
||||||
|
|
||||||
|
const computedValue = computed(getterOrOptions as any, debugOptions);
|
||||||
|
|
||||||
|
if (isGetter) {
|
||||||
|
return () => computedValue.value as ReadonlySignal<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createSignal(computedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSignal<T>(state: ShallowRef<T> | WritableComputedRef<T>): Signal<T> {
|
||||||
|
const signal = () => state.value;
|
||||||
|
|
||||||
|
signal.set = (value: T) => {
|
||||||
|
state.value = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.update = (updater: Updater<T>) => {
|
||||||
|
state.value = updater(state.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.mutate = (mutator: Mutator<T>) => {
|
||||||
|
mutator(state.value);
|
||||||
|
triggerRef(state);
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.getRef = () => state as Readonly<ShallowRef<Readonly<T>>>;
|
||||||
|
|
||||||
|
return signal;
|
||||||
|
}
|
@ -72,14 +72,18 @@ export default function useTable<ResponseData, ApiData, Column, Pagination exten
|
|||||||
|
|
||||||
const data = ref([]) as Ref<ApiData[]>;
|
const data = ref([]) as Ref<ApiData[]>;
|
||||||
|
|
||||||
|
const allColumns = ref(columns()) as Ref<Column[]>;
|
||||||
|
|
||||||
const columnChecks = ref(getColumnChecks(columns())) as Ref<TableColumnCheck[]>;
|
const columnChecks = ref(getColumnChecks(columns())) as Ref<TableColumnCheck[]>;
|
||||||
|
|
||||||
const $columns = computed(() => getColumns(columns(), columnChecks.value));
|
const $columns = computed(() => getColumns(columns(), columnChecks.value));
|
||||||
|
|
||||||
function reloadColumns() {
|
function reloadColumns() {
|
||||||
|
allColumns.value = columns();
|
||||||
|
|
||||||
const checkMap = new Map(columnChecks.value.map(col => [col.key, col.checked]));
|
const checkMap = new Map(columnChecks.value.map(col => [col.key, col.checked]));
|
||||||
|
|
||||||
const defaultChecks = getColumnChecks(columns());
|
const defaultChecks = getColumnChecks(allColumns.value);
|
||||||
|
|
||||||
columnChecks.value = defaultChecks.map(col => ({
|
columnChecks.value = defaultChecks.map(col => ({
|
||||||
...col,
|
...col,
|
||||||
|
@ -22,12 +22,7 @@ const columns = defineModel<NaiveUI.TableColumnCheck[]>('columns', {
|
|||||||
</NButton>
|
</NButton>
|
||||||
</template>
|
</template>
|
||||||
<VueDraggable v-model="columns" :animation="150" filter=".none_draggable">
|
<VueDraggable v-model="columns" :animation="150" filter=".none_draggable">
|
||||||
<div
|
<div v-for="item in columns" :key="item.key" class="h-36px flex-y-center rd-4px hover:(bg-primary bg-opacity-20)">
|
||||||
v-for="item in columns"
|
|
||||||
:key="item.key"
|
|
||||||
class="h-36px flex-y-center rd-4px hover:(bg-primary bg-opacity-20)"
|
|
||||||
:class="{ hidden: !item.visible }"
|
|
||||||
>
|
|
||||||
<icon-mdi-drag class="mr-8px h-full cursor-move text-icon" />
|
<icon-mdi-drag class="mr-8px h-full cursor-move text-icon" />
|
||||||
<NCheckbox v-model:checked="item.checked" class="none_draggable flex-1">
|
<NCheckbox v-model:checked="item.checked" class="none_draggable flex-1">
|
||||||
<template v-if="typeof item.title === 'function'">
|
<template v-if="typeof item.title === 'function'">
|
||||||
|
@ -250,26 +250,28 @@ function getColumnChecks<Column extends NaiveUI.TableColumn<any>>(
|
|||||||
const checks: TableColumnCheck[] = [];
|
const checks: TableColumnCheck[] = [];
|
||||||
|
|
||||||
cols.forEach(column => {
|
cols.forEach(column => {
|
||||||
|
const visible = getColumnVisible?.(column) ?? true;
|
||||||
|
|
||||||
if (isTableColumnHasKey(column)) {
|
if (isTableColumnHasKey(column)) {
|
||||||
checks.push({
|
checks.push({
|
||||||
key: column.key as string,
|
key: column.key as string,
|
||||||
title: column.title!,
|
title: column.title!,
|
||||||
checked: true,
|
checked: true,
|
||||||
visible: getColumnVisible?.(column) ?? true
|
visible
|
||||||
});
|
});
|
||||||
} else if (column.type === 'selection') {
|
} else if (column.type === 'selection') {
|
||||||
checks.push({
|
checks.push({
|
||||||
key: SELECTION_KEY,
|
key: SELECTION_KEY,
|
||||||
title: $t('common.check'),
|
title: $t('common.check'),
|
||||||
checked: true,
|
checked: true,
|
||||||
visible: getColumnVisible?.(column) ?? false
|
visible
|
||||||
});
|
});
|
||||||
} else if (column.type === 'expand') {
|
} else if (column.type === 'expand') {
|
||||||
checks.push({
|
checks.push({
|
||||||
key: EXPAND_KEY,
|
key: EXPAND_KEY,
|
||||||
title: $t('common.expandColumn'),
|
title: $t('common.expandColumn'),
|
||||||
checked: true,
|
checked: true,
|
||||||
visible: getColumnVisible?.(column) ?? false
|
visible
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user