|
@@ -1,9 +1,9 @@
|
|
<template>
|
|
<template>
|
|
<div class="actions">
|
|
<div class="actions">
|
|
- <span
|
|
|
|
- v-for="(action, i) in items"
|
|
|
|
- :class="{active: equal(selected, action)}"
|
|
|
|
- :key="action.key || i"
|
|
|
|
|
|
+ <span
|
|
|
|
+ v-for="(action, i) in items"
|
|
|
|
+ :class="{ active: equal(selected, action) }"
|
|
|
|
+ :key="action.key || i"
|
|
@click="clickHandler(action)"
|
|
@click="clickHandler(action)"
|
|
>
|
|
>
|
|
<ui-icon :type="action.icon" class="icon" />
|
|
<ui-icon :type="action.icon" class="icon" />
|
|
@@ -13,79 +13,87 @@
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
-import { useActive } from '@/hook';
|
|
|
|
-import { ref, toRaw, watchEffect, onBeforeUnmount, nextTick, watch } from 'vue'
|
|
|
|
|
|
+import { useActive } from "@/hook";
|
|
|
|
+import { ref, toRaw, watchEffect, onBeforeUnmount, nextTick, watch } from "vue";
|
|
|
|
|
|
-export type ActionsItem<T = any> = {
|
|
|
|
- icon: string,
|
|
|
|
- key?: T,
|
|
|
|
- text: string,
|
|
|
|
- action?: () => (() => void) | void
|
|
|
|
-}
|
|
|
|
-export type ActionsProps = { items: ActionsItem[], current?: ActionsItem | null, single?: boolean, }
|
|
|
|
|
|
+export type ActionsItem<T = any> = {
|
|
|
|
+ icon: string;
|
|
|
|
+ key?: T;
|
|
|
|
+ text: string;
|
|
|
|
+ action?: () => (() => void) | void;
|
|
|
|
+};
|
|
|
|
+export type ActionsProps = {
|
|
|
|
+ items: ActionsItem[];
|
|
|
|
+ current?: ActionsItem | null;
|
|
|
|
+ single?: boolean;
|
|
|
|
+};
|
|
|
|
|
|
-const props = defineProps<ActionsProps>()
|
|
|
|
-const emit = defineEmits<{ (e: 'update:current', data: ActionsItem | null): void }>()
|
|
|
|
-const equal = (a: ActionsItem | null, b: ActionsItem | null) => toRaw(a) === toRaw(b)
|
|
|
|
-const selected = ref<ActionsItem | null>(null)
|
|
|
|
|
|
+const props = defineProps<ActionsProps>();
|
|
|
|
+const emit = defineEmits<{ (e: "update:current", data: ActionsItem | null): void }>();
|
|
|
|
+const equal = (a: ActionsItem | null, b: ActionsItem | null) => toRaw(a) === toRaw(b);
|
|
|
|
+const selected = ref<ActionsItem | null>(null);
|
|
const clickHandler = (select: ActionsItem) => {
|
|
const clickHandler = (select: ActionsItem) => {
|
|
- selected.value = equal(selected.value, select) ? null : select
|
|
|
|
- emit('update:current', selected.value)
|
|
|
|
|
|
+ selected.value = equal(selected.value, select) ? null : select;
|
|
|
|
+ emit("update:current", selected.value);
|
|
|
|
+ console.log("update:current", selected.value);
|
|
if (props.single) {
|
|
if (props.single) {
|
|
- nextTick(() => selected.value && clickHandler(selected.value))
|
|
|
|
|
|
+ setTimeout(() => selected.value && clickHandler(selected.value), 16);
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+// watch(
|
|
|
|
+// () => props.current,
|
|
|
|
+// () => {
|
|
|
|
+// if (!props.current && selected.value) {
|
|
|
|
+// clickHandler(selected.value)
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// )
|
|
|
|
|
|
watch(
|
|
watch(
|
|
- () => props.current,
|
|
|
|
- () => {
|
|
|
|
- if (!props.current && selected.value) {
|
|
|
|
- clickHandler(selected.value)
|
|
|
|
|
|
+ selected,
|
|
|
|
+ (_n, _o, onCleanup) => {
|
|
|
|
+ if (selected.value?.action) {
|
|
|
|
+ const cleanup = selected.value.action();
|
|
|
|
+ cleanup && onCleanup(cleanup);
|
|
}
|
|
}
|
|
- }
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-watch(selected, (_n, _o, onCleanup) => {
|
|
|
|
- if (selected.value?.action) {
|
|
|
|
- const cleanup = selected.value.action()
|
|
|
|
- cleanup && onCleanup(cleanup)
|
|
|
|
- }
|
|
|
|
-}, { flush: 'sync' })
|
|
|
|
|
|
+ },
|
|
|
|
+ { flush: "sync" }
|
|
|
|
+);
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
onBeforeUnmount(() => {
|
|
- selected.value = null
|
|
|
|
-})
|
|
|
|
|
|
+ selected.value = null;
|
|
|
|
+});
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
.actions {
|
|
.actions {
|
|
display: flex;
|
|
display: flex;
|
|
gap: 10px;
|
|
gap: 10px;
|
|
-
|
|
|
|
|
|
+
|
|
span {
|
|
span {
|
|
flex: 1;
|
|
flex: 1;
|
|
height: 34px;
|
|
height: 34px;
|
|
- background: rgba(255,255,255,0.1);
|
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.1);
|
|
border-radius: 4px 4px 4px 4px;
|
|
border-radius: 4px 4px 4px 4px;
|
|
opacity: 1;
|
|
opacity: 1;
|
|
display: flex;
|
|
display: flex;
|
|
align-items: center;
|
|
align-items: center;
|
|
justify-content: center;
|
|
justify-content: center;
|
|
- color: rgba(255,255,255,0.6);
|
|
|
|
|
|
+ color: rgba(255, 255, 255, 0.6);
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
- transition: all .3s ease;
|
|
|
|
|
|
+ transition: all 0.3s ease;
|
|
|
|
|
|
.icon {
|
|
.icon {
|
|
margin-right: 4px;
|
|
margin-right: 4px;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
&:hover,
|
|
&:hover,
|
|
&.active {
|
|
&.active {
|
|
- background: rgba(0,200,175,0.16);
|
|
|
|
- color: #00C8AF;
|
|
|
|
|
|
+ background: rgba(0, 200, 175, 0.16);
|
|
|
|
+ color: #00c8af;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-</style>
|
|
|
|
|
|
+</style>
|