| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- <!-- 主页 -->
- <template>
- <div class="bg-gray-50 min-h-screen">
- <!-- 顶部信息栏 -->
- <PageHeader :show-back="false" />
- <!-- 主内容区域 -->
- <main class="container mx-auto px-6 py-12 pb-40">
- <div class="text-center mb-16">
- <h1 class="text-4xl font-bold text-gray-800 mb-4">智能仓储管理系统</h1>
- <p class="text-xl text-gray-600 max-w-2xl mx-auto">高效管理物料流转,实时监控库存状态,优化仓储作业流程</p>
- </div>
- <!-- 数据概览卡片 -->
- <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-16">
- <div
- v-for="stat in statistics" :key="stat.title" class="bg-white rounded-xl shadow-md p-6 border-l-4"
- :class="getStatColorClasses(stat.color, 'border')"
- >
- <div class="flex justify-between items-start">
- <div>
- <p class="text-gray-500 text-sm">{{ stat.title }}</p>
- <p class="text-3xl font-bold mt-2">{{ stat.value }}</p>
- </div>
- <div class="p-3 rounded-lg" :class="getStatColorClasses(stat.color, 'bg')">
- <i class="text-xl" :class="['fas', stat.icon, getStatColorClasses(stat.color, 'text')]" />
- </div>
- </div>
- <div class="mt-4">
- <p class="text-sm" :class="stat.trend > 0 ? 'text-green-500' : 'text-red-500'">
- <i class="mr-1" :class="stat.trend > 0 ? 'fas fa-arrow-up' : 'fas fa-arrow-down'" />{{ stat.changeText }}
- </p>
- </div>
- </div>
- </div>
- <!-- 物料分类区域 -->
- <div class="mb-16">
- <h2 class="text-2xl font-bold text-gray-800 mb-6">物料分类</h2>
- <div class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-6">
- <div
- v-for="category in materialCategories" :key="category.name"
- class="bg-white rounded-lg shadow-sm p-4 text-center cursor-pointer hover:shadow-md transition-shadow"
- >
- <div class="w-full h-20 overflow-hidden mb-3 rounded-lg">
- <img :src="category.image" :alt="category.name" class="w-full h-full object-cover object-top" />
- </div>
- <p class="font-medium">{{ category.name }}</p>
- <p class="text-gray-500 text-sm">{{ category.count }} 种</p>
- </div>
- </div>
- </div>
- <!-- 最近操作记录 -->
- <div>
- <div class="flex justify-between items-center mb-6">
- <h2 class="text-2xl font-bold text-gray-800">最近操作记录</h2>
- <button class="text-blue-500 hover:text-blue-700 font-medium" @click="viewAllRecords">
- 查看全部 <i class="fas fa-chevron-right ml-1 text-xs" />
- </button>
- </div>
- <div class="bg-white rounded-xl shadow-sm overflow-hidden">
- <a-table :columns="columns" :data-source="recentRecords" :pagination="false" :scroll="{ x: true }">
- <template #bodyCell="{ column, record }">
- <template v-if="column.key === 'operationType'">
- <span class="px-3 py-1 rounded-full text-sm" :class="getOperationTypeClass(record.operationType)">
- {{ record.operationType }}
- </span>
- </template>
- <template v-if="column.key === 'status'">
- <span class="text-green-500">
- <i class="fas fa-check-circle mr-1" />{{ record.status }}
- </span>
- </template>
- </template>
- </a-table>
- </div>
- </div>
- </main>
- <!-- 底部圆形功能按钮 -->
- <footer class="fixed bottom-0 left-0 right-0 bg-white shadow-lg py-6 z-50">
- <div class="container mx-auto px-6">
- <div class="flex justify-center space-x-12">
- <template v-if="isOut">
- <button
- v-for="action in outButtons" :key="action.label" class="circle-button text-white"
- :class="getButtonClass(action.color)" @click="handleAction(action.action)"
- >
- <i :class="`fas ${action.icon}`" />
- <span>{{ action.label }}</span>
- </button>
- </template>
- <template v-if="!isOut">
- <button
- v-for="action in inButtons" :key="action.label" class="circle-button text-white"
- :class="getButtonClass(action.color)" @click="handleAction(action.action)"
- >
- <i :class="`fas ${action.icon}`" />
- <span>{{ action.label }}</span>
- </button>
- </template>
- </div>
- </div>
- </footer>
- <!-- 拣货确认弹窗 -->
- <a-modal
- v-model:open="pickingModalVisible" title="请确认您要进行的操作?" :closable="true" :mask-closable="false"
- @ok="handlePickingConfirm" @cancel="pickingModalVisible = false"
- >
- <template #footer>
- <a-button @click="handlePickingCancel">否</a-button>
- <a-button type="primary" danger @click="handlePickingConfirm">是</a-button>
- </template>
- <p>您是否已经申请了领料。</p>
- </a-modal>
- </div>
- <Loading v-if="loading" />
- </template>
- <script setup>
- import { ref, reactive, onMounted } from 'vue';
- import { useRouter } from 'vue-router';
- import PageHeader from '../common/PageHeader.vue';
- import { cfStockInLeave } from '../api/stockIn.js';
- import { message } from 'ant-design-vue';
- // 路由
- const router = useRouter();
- // 加载状态
- const loading = ref(false);
- // 弹窗控制
- const pickingModalVisible = ref(false);
- // 是否为外侧屏幕
- const isOut = ref(false);
- // 初始化时从localStorage读取isOut值
- onMounted(() => {
- const storedIsOut = localStorage.getItem('isOut');
- if (storedIsOut !== null) {
- isOut.value = storedIsOut === 'true';
- }
- });
- // 统计数据
- const statistics = reactive([
- {
- title: '总库存量',
- value: '12,847',
- icon: 'fa-boxes',
- color: 'blue',
- trend: 1,
- changeText: '较昨日 +2.3%',
- },
- {
- title: '今日入库',
- value: '1,248',
- icon: 'fa-truck-loading',
- color: 'green',
- trend: 1,
- changeText: '较昨日 +5.7%',
- },
- {
- title: '今日出库',
- value: '36',
- icon: 'fa-tasks',
- color: 'yellow',
- trend: -1,
- changeText: '较昨日 -1.2%',
- },
- {
- title: '库存周转率',
- value: '4.2',
- icon: 'fa-sync-alt',
- color: 'purple',
- trend: 1,
- changeText: '较上月 +0.8%',
- },
- ]);
- // 物料分类
- const materialCategories = reactive([
- {
- name: '电子元件',
- count: 248,
- image: 'https://ai-public.mastergo.com/ai/img_res/b752a3a8cb35d2b915a23b12981693d8.jpg',
- },
- {
- name: '机械零件',
- count: 186,
- image: 'https://ai-public.mastergo.com/ai/img_res/1d4cf39dc61dadac88754be3bd525e3c.jpg',
- },
- {
- name: '化工原料',
- count: 92,
- image: 'https://ai-public.mastergo.com/ai/img_res/4f12a387c9413be821c1d203bda09622.jpg',
- },
- {
- name: '包装材料',
- count: 64,
- image: 'https://ai-public.mastergo.com/ai/img_res/c2d2f76aebbef43067223fd11e120c49.jpg',
- },
- {
- name: '办公用品',
- count: 127,
- image: 'https://ai-public.mastergo.com/ai/img_res/404ab042346c15d0722e9d2eae6bda99.jpg',
- },
- {
- name: '维修工具',
- count: 89,
- image: 'https://ai-public.mastergo.com/ai/img_res/048d0b638d5cb1f1bd11916983979fed.jpg',
- },
- ]);
- // 表格列定义
- const columns = [
- {
- title: '时间',
- dataIndex: 'time',
- key: 'time',
- width: 150,
- },
- {
- title: '操作类型',
- dataIndex: 'operationType',
- key: 'operationType',
- width: 120,
- },
- {
- title: '物料名称',
- dataIndex: 'materialName',
- key: 'materialName',
- width: 200,
- },
- {
- title: '数量',
- dataIndex: 'quantity',
- key: 'quantity',
- width: 100,
- },
- {
- title: '操作员',
- dataIndex: 'operator',
- key: 'operator',
- width: 100,
- },
- {
- title: '状态',
- dataIndex: 'status',
- key: 'status',
- width: 120,
- },
- ];
- // 最近操作记录
- const recentRecords = reactive([
- {
- key: '1',
- time: '2023-12-15 14:32',
- operationType: '入库',
- materialName: '集成电路芯片 IC-2023',
- quantity: '+500',
- operator: '张伟',
- status: '已完成',
- },
- {
- key: '2',
- time: '2023-12-15 13:45',
- operationType: '领料',
- materialName: '电阻 R-1KΩ 1/4W',
- quantity: '-200',
- operator: '李娜',
- status: '已完成',
- },
- {
- key: '3',
- time: '2023-12-15 11:20',
- operationType: '还料',
- materialName: '电容 C-100μF 50V',
- quantity: '+50',
- operator: '王强',
- status: '已完成',
- },
- {
- key: '4',
- time: '2023-12-15 09:15',
- operationType: '出库',
- materialName: '连接器 CONN-USB-C',
- quantity: '-150',
- operator: '赵敏',
- status: '已完成',
- },
- {
- key: '5',
- time: '2023-12-14 16:40',
- operationType: '入库',
- materialName: '传感器 SHT-30',
- quantity: '+300',
- operator: '孙磊',
- status: '已完成',
- },
- ]);
- // 底部操作按钮
- const outButtons = reactive([
- {
- label: '领料',
- icon: 'fa-hand-holding',
- color: 'blue',
- action: 'materialOut',
- },
- {
- label: '拣货',
- icon: 'fa-undo',
- color: 'green',
- action: 'materialReturn',
- },
- {
- label: '还料',
- icon: 'fa-arrow-up',
- color: 'yellow',
- action: 'materialIn',
- },
- {
- label: 'AGV RFID校验',
- icon: 'fa-wifi',
- color: 'red',
- action: 'agvRfidRecognition',
- },
- {
- label: '成品入库',
- icon: 'fa-boxes',
- color: 'blue',
- action: 'finishedProductIn',
- },
- // 测试待删除
- // {
- // label: '还料区管理',
- // icon: 'fa-undo',
- // color: 'green',
- // action: 'returnManagement',
- // },
- // {
- // label: '取料区管理',
- // icon: 'fa-arrow-down',
- // color: 'red',
- // action: 'deliverManagement',
- // },
- ]);
- const inButtons = reactive([
- {
- label: '出库确认',
- icon: 'fa-undo',
- color: 'blue',
- action: 'materialOutLeave',
- },
- {
- label: '还料离开',
- icon: 'fa-arrow-down',
- color: 'green',
- action: 'materialInLeave',
- },
- {
- label: '成品出库',
- icon: 'fa-boxes',
- color: 'red',
- action: 'finishedProductOut',
- },
- ]);
- // 查看全部记录逻辑
- const viewAllRecords = () => {
- console.log('查看全部');
- };
- // 拣货确认弹窗处理
- const handlePickingConfirm = () => {
- pickingModalVisible.value = false;
- router.push('/order-picking');
- };
- // 去领料
- const handlePickingCancel = () => {
- pickingModalVisible.value = false;
- router.push('/stock-requisition');
- };
- // 根据不同的action执行不同的逻辑
- const handleAction = action => {
- console.log('Action clicked:', action);
- switch (action) {
- case 'materialOut':
- // 领料 - 跳转到领料界面
- router.push('/stock-requisition');
- break;
- case 'materialReturn':
- // 拣货 - 显示确认弹窗
- pickingModalVisible.value = true;
- break;
- case 'materialOutLeave':
- // 领料出库离开
- router.push('/outbound-confirm');
- break;
- case 'materialReturnLeave':
- // 还料出库离开
- break;
- case 'agvRfidRecognition':
- // RFID识别
- router.push('/agv-rfid-recognition');
- break;
- case 'materialIn':
- // 还料 - 跳转到还料界面
- router.push('/in-confirm');
- break;
- case 'materialInLeave':
- // 还料出库离开
- validateMaterialInLeave();
- break;
- // 测试待删除
- case 'returnManagement':
- router.push('/return-management');
- break;
- case 'deliverManagement':
- router.push('/delivery-management');
- break;
- }
- };
- // 校验还料离开时是否带有工装设备信息
- const validateMaterialInLeave = async () => {
- loading.value = true;
- try {
- const res = await cfStockInLeave();
- if (res.errorCode === 0) {
- if (res.datas && res.datas.length > 0) {
- router.push('/in-confirm?isLeave=true');
- } else {
- message.success('您已完成还料操作,请在闸机开门后离开');
- }
- } else {
- message.warning(res.errorMessage);
- }
- } catch (error) {
- console.error('校验还料离开时是否带有工装设备信息失败:', error);
- message.error('校验还料离开时是否带有工装设备信息失败');
- } finally {
- loading.value = false;
- }
- };
- // 渲染样式
- const getOperationTypeClass = type => {
- const classMap = {
- '入库': 'bg-green-100 text-green-800',
- '领料': 'bg-blue-100 text-blue-800',
- '还料': 'bg-yellow-100 text-yellow-800',
- '出库': 'bg-red-100 text-red-800',
- };
- return classMap[type] || 'bg-gray-100 text-gray-800';
- };
- // 按钮样式
- const getButtonClass = color => {
- const colorMap = {
- blue: 'bg-blue-500 hover:bg-blue-600',
- green: 'bg-green-500 hover:bg-green-600',
- yellow: 'bg-yellow-500 hover:bg-yellow-600',
- red: 'bg-red-500 hover:bg-red-600',
- };
- return colorMap[color] || 'bg-gray-500 hover:bg-gray-600';
- };
- // 统计样式
- const getStatColorClasses = (color, type) => {
- const colorMap = {
- blue: {
- border: 'border-blue-500',
- bg: 'bg-blue-100',
- text: 'text-blue-500',
- },
- green: {
- border: 'border-green-500',
- bg: 'bg-green-100',
- text: 'text-green-500',
- },
- yellow: {
- border: 'border-yellow-500',
- bg: 'bg-yellow-100',
- text: 'text-yellow-500',
- },
- purple: {
- border: 'border-purple-500',
- bg: 'bg-purple-100',
- text: 'text-purple-500',
- },
- };
- return colorMap[color]?.[type] || '';
- };
- </script>
- <style scoped>
- /* Additional component-specific styles if needed */
- </style>
|