<script lang="ts" setup>
|
import { computed } from 'vue';
|
|
import { IconifyIcon } from '@vben/icons';
|
|
import { useHomeAccess } from '../use-home-access';
|
|
defineOptions({ name: 'DashboardQuickActions' });
|
|
const emit = defineEmits<{
|
navigate: [name: string];
|
}>();
|
|
interface QuickAction {
|
title: string;
|
icon: string;
|
route: string;
|
gradient: string;
|
shadow: string;
|
}
|
|
const actions: QuickAction[] = [
|
{ title: '生产工单', icon: 'lucide:file-text', route: 'MesProWorkOrder', gradient: 'from-blue-500 to-cyan-500', shadow: 'shadow-blue-500/15' },
|
{ title: '生产报工', icon: 'lucide:check-square', route: 'MesProFeedback', gradient: 'from-emerald-500 to-green-500', shadow: 'shadow-emerald-500/15' },
|
{ title: '质检管理', icon: 'lucide:clipboard-check', route: 'MesQcRecord', gradient: 'from-orange-500 to-amber-500', shadow: 'shadow-orange-500/15' },
|
{ title: '设备点检', icon: 'lucide:settings', route: 'MesDvMachinery', gradient: 'from-violet-500 to-purple-500', shadow: 'shadow-violet-500/15' },
|
{ title: '生产排程', icon: 'lucide:calendar-range', route: 'MesProScheduling', gradient: 'from-cyan-500 to-teal-500', shadow: 'shadow-cyan-500/15' },
|
{ title: '物料库存', icon: 'lucide:package-search', route: 'WlsMaterialStock', gradient: 'from-indigo-500 to-blue-500', shadow: 'shadow-indigo-500/15' },
|
{ title: '工艺路线', icon: 'lucide:route', route: 'MesPdRouting', gradient: 'from-teal-500 to-emerald-500', shadow: 'shadow-teal-500/15' },
|
{ title: '数据报表', icon: 'lucide:bar-chart-big', route: 'MesHomeIndex', gradient: 'from-pink-500 to-rose-500', shadow: 'shadow-pink-500/15' },
|
];
|
|
const { canNavigate } = useHomeAccess();
|
const accessibleActions = computed(() => actions.filter((action) => canNavigate(action.route)));
|
</script>
|
|
<template>
|
<div v-if="accessibleActions.length" class="glass-card rounded-2xl p-5">
|
<h3 class="mb-4 text-sm font-semibold text-gray-800 dark:text-gray-100">快捷操作</h3>
|
<div class="grid grid-cols-4 gap-3 sm:grid-cols-8">
|
<div
|
v-for="action in accessibleActions"
|
:key="action.route"
|
class="group flex cursor-pointer flex-col items-center gap-2 rounded-xl p-3 transition-all duration-300 hover:-translate-y-1"
|
@click="emit('navigate', action.route)"
|
>
|
<div
|
class="flex size-10 items-center justify-center rounded-xl bg-gradient-to-br transition-shadow duration-300 group-hover:shadow-lg"
|
:class="[action.gradient, action.shadow]"
|
>
|
<IconifyIcon :icon="action.icon" class="size-5 text-white" />
|
</div>
|
<span class="text-xs font-medium text-gray-600 dark:text-gray-400">{{ action.title }}</span>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<style scoped>
|
.glass-card {
|
background: linear-gradient(135deg, rgba(255,255,255,0.85), rgba(255,255,255,0.55));
|
backdrop-filter: blur(20px);
|
-webkit-backdrop-filter: blur(20px);
|
border: 1px solid rgba(255,255,255,0.6);
|
box-shadow:
|
0 4px 24px rgba(0,0,0,0.04),
|
0 1px 4px rgba(0,0,0,0.02),
|
inset 0 1px 0 rgba(255,255,255,0.8);
|
}
|
|
.dark .glass-card {
|
background: linear-gradient(135deg, rgba(30,30,55,0.75), rgba(20,20,40,0.5));
|
border: 1px solid rgba(255,255,255,0.08);
|
box-shadow:
|
0 4px 24px rgba(0,0,0,0.3),
|
0 1px 4px rgba(0,0,0,0.2),
|
inset 0 1px 0 rgba(255,255,255,0.04);
|
}
|
</style>
|