Files

102 lines
13 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="home-page">
<main class="home-shell">
<section class="hero-card">
<div class="hero-copy">
<span class="eyebrow">MRLEE · 生产运营中心</span>
<h1>让每一道工序,都清晰可追溯</h1>
<p>从订单录入、生产执行到异常闭环,集中掌握现场进度与质量状态。</p>
<div class="hero-actions">
<NuxtLink to="/produce/data-entry"><el-button type="primary" size="large"><el-icon><Plus /></el-icon>开始生产录入</el-button></NuxtLink>
<NuxtLink to="/produce/query"><el-button size="large" plain>查看订单全流程</el-button></NuxtLink>
</div>
</div>
<div class="hero-visual" aria-hidden="true">
<div class="orb orb-one"></div><div class="orb orb-two"></div>
<div class="hero-panel">
<div class="panel-topline"><span>今日生产概览</span><span class="live-dot">实时</span></div>
<strong>92.8<span>%</span></strong>
<div class="progress-track"><i style="width: 92.8%"></i></div>
<div class="panel-footer"><span>计划达成率</span><span>较昨日 +6.4%</span></div>
</div>
</div>
</section>
<section class="metric-grid" aria-label="生产指标">
<article v-for="metric in metrics" :key="metric.label" class="metric-card">
<div class="metric-icon" :class="metric.tone"><Icon :icon="metric.icon" /></div>
<div class="metric-content"><span>{{ metric.label }}</span><strong>{{ metric.value }}</strong><small :class="metric.trendTone">{{ metric.trend }}</small></div>
</article>
</section>
<section class="section-block">
<div class="section-heading"><div><span class="section-kicker">QUICK ACCESS</span><h2>快捷工作入口</h2></div><span class="section-hint">常用功能,一键直达</span></div>
<div class="quick-grid">
<NuxtLink v-for="item in quickLinks" :key="item.title" :to="item.to" class="quick-card">
<div class="quick-icon" :class="item.tone"><Icon :icon="item.icon" /></div>
<div><strong>{{ item.title }}</strong><span>{{ item.description }}</span></div><el-icon class="arrow"><ArrowRight /></el-icon>
</NuxtLink>
</div>
</section>
<section class="dashboard-grid">
<article class="surface-card process-card">
<div class="card-heading"><div><span class="section-kicker">ORDER FLOW</span><h2>订单流程进度</h2></div><NuxtLink to="/produce/query">查看全部 <el-icon><ArrowRight /></el-icon></NuxtLink></div>
<div class="process-list"><div v-for="order in orders" :key="order.number" class="process-row"><div class="order-title"><strong>{{ order.number }}</strong><span>{{ order.product }}</span></div><div class="process-track"><i :style="{ width: `${order.progress}%` }"></i></div><div class="process-meta"><span>{{ order.stage }}</span><b>{{ order.progress }}%</b></div></div></div>
</article>
<article class="surface-card activity-card">
<div class="card-heading"><div><span class="section-kicker">RECENT ACTIVITY</span><h2>现场动态</h2></div><NuxtLink to="/produce/query">更多 <el-icon><ArrowRight /></el-icon></NuxtLink></div>
<div class="activity-list"><div v-for="activity in activities" :key="activity.time + activity.title" class="activity-row"><span class="activity-dot" :class="activity.tone"></span><div><strong>{{ activity.title }}</strong><span>{{ activity.description }}</span></div><time>{{ activity.time }}</time></div></div>
</article>
</section>
<section class="insight-banner"><div><span class="section-kicker">DATA INSIGHT</span><h2>用数据发现现场的下一步</h2><p>按日、按月查看工序与步骤统计,及时识别瓶颈并优化产能。</p></div><NuxtLink to="/produce/statistics/monthly"><el-button type="primary">进入生产统计 <el-icon><ArrowRight /></el-icon></el-button></NuxtLink></section>
</main>
<Advertisement type="float" position="bottom" :offset="0" :limit="1" :closable="true" />
</div>
</template>
<script setup lang="ts">
import { ArrowRight, Plus } from '@element-plus/icons-vue'
import { Icon } from '~/components/icon'
import Advertisement from '~/components/advertisement/index.vue'
const metrics = [
{ label: '今日完成订单', value: '128', trend: '+12.6% 较昨日', icon: 'ri:archive-stack-line', tone: 'blue', trendTone: 'up' },
{ label: '生产中订单', value: '36', trend: '进行中', icon: 'ri:loader-4-line', tone: 'violet', trendTone: 'neutral' },
{ label: '待处理异常', value: '08', trend: '需及时关注', icon: 'ri:error-warning-line', tone: 'orange', trendTone: 'warning' },
{ label: '设备运行率', value: '96.4%', trend: '+2.1% 较昨日', icon: 'ri:settings-5-line', tone: 'green', trendTone: 'up' },
]
const quickLinks = [
{ title: '生产录入', description: '录入订单与生产数据', to: '/produce/data-entry', icon: 'ri:scan-2-line', tone: 'blue' },
{ title: '异常提报', description: '快速记录现场异常', to: '/produce/exception', icon: 'ri:alarm-warning-line', tone: 'orange' },
{ title: '维修记录', description: '跟进维修与备件使用', to: '/produce/repair', icon: 'ri:tools-line', tone: 'violet' },
{ title: '订单查询', description: '追踪订单全流程', to: '/produce/query', icon: 'ri:search-eye-line', tone: 'green' },
]
const orders = [
{ number: 'MO-20260902-018', product: '精密控制模块', stage: '装配工序', progress: 86 },
{ number: 'MO-20260902-021', product: '智能传感器组件', stage: '功能测试', progress: 64 },
{ number: 'MO-20260902-024', product: '工业连接器', stage: '来料检验', progress: 32 },
]
const activities = [
{ title: '异常提报已处理', description: '订单 MO-20260902-018 · 贴合不良', time: '10:42', tone: 'green' },
{ title: '维修记录已提交', description: '设备 SMT-03 · 更换送料器', time: '10:18', tone: 'violet' },
{ title: '生产录入完成', description: '订单 MO-20260902-021 · 功能测试', time: '09:56', tone: 'blue' },
{ title: '新异常待确认', description: '订单 MO-20260902-024 · 外观瑕疵', time: '09:31', tone: 'orange' },
]
</script>
<style lang="scss" scoped>
.home-page { min-height: 100%; background: #f5f7fb; color: #18243a; }
.home-shell { max-width: 1440px; margin: 0 auto; padding: 32px 40px 72px; }
.hero-card { position: relative; display: flex; min-height: 330px; overflow: hidden; border-radius: 24px; background: linear-gradient(120deg, #132d5b 0%, #1d4c87 60%, #2875a7 100%); color: #fff; box-shadow: 0 16px 40px rgba(21, 52, 97, .16); }
.hero-copy { position: relative; z-index: 1; max-width: 650px; padding: 52px 56px; }.eyebrow, .section-kicker { font-size: 11px; letter-spacing: .18em; font-weight: 700; color: #78c8ff; }.hero-copy h1 { margin: 18px 0 14px; font-size: clamp(30px, 4vw, 48px); line-height: 1.15; letter-spacing: -.03em; }.hero-copy p { max-width: 510px; margin: 0; color: rgba(255,255,255,.72); font-size: 16px; line-height: 1.8; }.hero-actions { display: flex; gap: 12px; margin-top: 32px; }.hero-actions :deep(.el-button) { border-radius: 10px; padding: 0 20px; }.hero-actions :deep(.el-button--default) { color: #fff; border-color: rgba(255,255,255,.28); background: rgba(255,255,255,.08); }
.hero-visual { position: absolute; inset: 0 0 0 54%; }.orb { position: absolute; border-radius: 50%; }.orb-one { width: 330px; height: 330px; top: -70px; right: 70px; background: rgba(121, 213, 255, .14); }.orb-two { width: 220px; height: 220px; right: -30px; bottom: -80px; background: rgba(255, 255, 255, .1); }.hero-panel { position: absolute; top: 76px; right: 12%; width: 260px; padding: 24px; border: 1px solid rgba(255,255,255,.16); border-radius: 18px; background: rgba(8, 33, 75, .42); backdrop-filter: blur(12px); }.panel-topline, .panel-footer { display: flex; justify-content: space-between; align-items: center; color: rgba(255,255,255,.66); font-size: 12px; }.live-dot { color: #8df0bb; }.live-dot::before { content: ''; display: inline-block; width: 6px; height: 6px; margin-right: 5px; border-radius: 50%; background: #62e7a4; }.hero-panel strong { display: block; margin: 24px 0 14px; font-size: 52px; letter-spacing: -.06em; }.hero-panel strong span { margin-left: 3px; font-size: 24px; }.progress-track { height: 7px; overflow: hidden; border-radius: 5px; background: rgba(255,255,255,.14); }.progress-track i { display: block; height: 100%; border-radius: inherit; background: #75d5ff; }.panel-footer { margin-top: 12px; }.panel-footer span:last-child { color: #8df0bb; }
.metric-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 18px; }.metric-card, .quick-card, .surface-card, .insight-banner { border: 1px solid #e7ebf3; background: #fff; box-shadow: 0 5px 18px rgba(28, 50, 86, .04); }.metric-card { display: flex; align-items: center; gap: 14px; padding: 20px; border-radius: 16px; }.metric-icon, .quick-icon { display: grid; place-items: center; flex: 0 0 auto; border-radius: 12px; }.metric-icon { width: 44px; height: 44px; font-size: 21px; }.metric-content { display: grid; gap: 4px; }.metric-content > span { color: #8490a5; font-size: 12px; }.metric-content strong { font-size: 26px; line-height: 1; letter-spacing: -.04em; }.metric-content small { font-size: 11px; }.up { color: #20aa6a; }.warning { color: #e88b2b; }.neutral { color: #8792a8; }.blue { color: #3a86f7; background: #eaf3ff; }.violet { color: #8063e8; background: #f0edff; }.orange { color: #e99532; background: #fff2df; }.green { color: #24a873; background: #e6f8f0; }
.section-block { margin-top: 42px; }.section-heading, .card-heading { display: flex; align-items: end; justify-content: space-between; }.section-heading h2, .card-heading h2, .insight-banner h2 { margin: 7px 0 0; font-size: 22px; letter-spacing: -.02em; }.section-hint { color: #98a3b5; font-size: 13px; }.quick-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 18px; }.quick-card { position: relative; display: flex; align-items: center; gap: 14px; padding: 18px; border-radius: 15px; transition: transform .2s ease, box-shadow .2s ease; }.quick-card:hover { transform: translateY(-3px); box-shadow: 0 12px 26px rgba(28, 50, 86, .1); }.quick-icon { width: 42px; height: 42px; font-size: 20px; }.quick-card strong, .quick-card span { display: block; }.quick-card strong { font-size: 15px; }.quick-card span { margin-top: 5px; color: #8a95a8; font-size: 12px; }.arrow { margin-left: auto; color: #aab4c4; }
.dashboard-grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: 16px; margin-top: 18px; }.surface-card { padding: 24px; border-radius: 16px; }.card-heading a { display: inline-flex; align-items: center; gap: 3px; color: #4b8bf5; font-size: 12px; }.process-list, .activity-list { margin-top: 22px; }.process-row + .process-row { margin-top: 22px; }.order-title { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }.order-title strong { font-size: 13px; }.order-title span { color: #8a95a8; font-size: 12px; }.process-track { height: 8px; overflow: hidden; border-radius: 6px; background: #edf1f6; }.process-track i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #4b8bf5, #71c9f5); }.process-meta { display: flex; justify-content: space-between; margin-top: 7px; color: #8a95a8; font-size: 11px; }.process-meta b { color: #4b8bf5; }.activity-row { display: flex; align-items: flex-start; gap: 11px; }.activity-row + .activity-row { margin-top: 19px; }.activity-dot { width: 8px; height: 8px; margin-top: 5px; border-radius: 50%; box-shadow: 0 0 0 4px currentColor; opacity: .75; }.activity-row div { flex: 1; }.activity-row strong, .activity-row span { display: block; }.activity-row strong { font-size: 13px; }.activity-row span { margin-top: 4px; color: #8a95a8; font-size: 12px; }.activity-row time { color: #a5afbd; font-size: 11px; }
.insight-banner { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-top: 18px; padding: 28px 32px; border-radius: 16px; background: linear-gradient(100deg, #f2f7ff, #fbfcff); }.insight-banner p { margin: 9px 0 0; color: #8490a5; font-size: 13px; }.insight-banner :deep(.el-button) { border-radius: 9px; }
@media (max-width: 1100px) { .home-shell { padding: 24px; }.hero-card { min-height: 360px; }.hero-visual { opacity: .75; right: -80px; }.metric-grid, .quick-grid { grid-template-columns: repeat(2, 1fr); }.dashboard-grid { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .home-shell { padding: 16px 12px 48px; }.hero-card { min-height: 440px; }.hero-copy { padding: 34px 26px; }.hero-copy h1 { font-size: 32px; }.hero-copy p { font-size: 14px; }.hero-actions { flex-direction: column; align-items: flex-start; }.hero-visual { inset: auto 0 20px; height: 150px; opacity: .9; }.hero-panel { top: 10px; right: 26px; width: 220px; padding: 17px; }.hero-panel strong { margin: 13px 0 9px; font-size: 38px; }.metric-grid, .quick-grid { grid-template-columns: 1fr; }.metric-card { padding: 16px; }.section-block { margin-top: 32px; }.section-heading h2, .card-heading h2 { font-size: 19px; }.section-hint { display: none; }.surface-card { padding: 18px; }.insight-banner { align-items: flex-start; flex-direction: column; padding: 22px; } }
</style>