feat: harden ai agent admin workflow experience

This commit is contained in:
2026-06-22 04:50:11 +08:00
parent ae29c24529
commit 4ec846a702
385 changed files with 61461 additions and 5886 deletions
@@ -1,3 +1,4 @@
export * from './authentication';
export * from './basic';
export * from './iframe';
export * from './widgets';
@@ -1,9 +1,8 @@
<script lang="ts" setup>
import { computed, nextTick } from 'vue';
import { VbenButton } from '@vben-core/shadcn-ui';
import { computed } from 'vue';
interface Props {
modelValue?: boolean;
/**
* 类型
*/
@@ -15,81 +14,43 @@ defineOptions({
});
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
type: 'normal',
});
const isDark = defineModel<boolean>();
const emit = defineEmits<{
'update:modelValue': [value: boolean];
}>();
const theme = computed(() => {
return isDark.value ? 'light' : 'dark';
return props.modelValue ? 'light' : 'dark';
});
const bindProps = computed(() => {
const type = props.type;
const buttonClass = computed(() => {
const base =
'inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50';
const mode =
props.type === 'normal'
? 'h-9 rounded-md px-4 py-2 text-sm hover:bg-heavy hover:text-heavy-foreground'
: 'h-8 w-8 rounded-full px-1 text-lg hover:bg-accent hover:text-accent-foreground text-foreground/80';
return type === 'normal'
? {
variant: 'heavy' as const,
}
: {
class: 'rounded-full',
size: 'icon' as const,
style: { padding: '7px' },
variant: 'icon' as const,
};
return `${base} ${mode}`;
});
function toggleTheme(event: MouseEvent) {
const isAppearanceTransition =
// @ts-expect-error
document.startViewTransition &&
!window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!isAppearanceTransition || !event) {
isDark.value = !isDark.value;
return;
}
const x = event.clientX;
const y = event.clientY;
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
);
// @ts-ignore startViewTransition
const transition = document.startViewTransition(async () => {
isDark.value = !isDark.value;
await nextTick();
});
transition.ready.then(() => {
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
];
const animate = document.documentElement.animate(
{
clipPath: isDark.value ? [...clipPath].reverse() : clipPath,
},
{
duration: 450,
easing: 'ease-in',
pseudoElement: isDark.value
? '::view-transition-old(root)'
: '::view-transition-new(root)',
},
);
animate.onfinish = () => {
transition.skipTransition();
};
});
event.preventDefault();
emit('update:modelValue', !props.modelValue);
}
</script>
<template>
<VbenButton
<button
:aria-label="theme"
:class="[`is-${theme}`]"
:class="[buttonClass, `is-${theme}`]"
aria-live="polite"
class="theme-toggle cursor-pointer border-none bg-none hover:animate-[shrink_0.3s_ease-in-out]"
v-bind="bindProps"
style="padding: 7px"
type="button"
@click.stop="toggleTheme"
>
<svg aria-hidden="true" height="24" viewBox="0 0 24 24" width="24">
@@ -121,7 +82,7 @@ function toggleTheme(event: MouseEvent) {
<line x1="18.36" x2="19.78" y1="5.64" y2="4.22" />
</g>
</svg>
</VbenButton>
</button>
</template>
<style scoped>