Project

General

Profile

Feature #177 » 倉庫作業明細_0715.html

楷翊 張, 07/22/2026 07:12 AM

 
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>物流作業全局看板</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<style>
.focus-ring {
transition: all 0.2s;
}
.focus-ring:focus {
border-color: #6366f1;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.5);
outline: none;
}
/* 作業類型標籤 */
.type-badge {
padding: 0.35rem 0.75rem;
border-radius: 0.75rem;
font-weight: 700;
font-size: 0.85rem;
display: inline-block;
text-align: center;
width: 80px;
}
.type-receipt { background-color: #e0e7ff; color: #3730a3; border: 1px solid #c7d2fe; } /* 靛藍 - 入庫 */
.type-shipping { background-color: #dbeafe; color: #1e40af; border: 1px solid #bfdbfe; } /* 純藍 - 出貨 */
.type-mat-issue { background-color: #fef3c7; color: #92400e; border: 1px solid #fde68a; } /* 琥珀 - 發料 */
.type-sup-receipt { background-color: #ccfbf1; color: #115e59; border: 1px solid #99f6e4; } /* 翠綠 - 收料 */

/* QC 檢驗標籤樣式 */
.qa-badge {
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-weight: 600;
font-size: 0.75rem;
display: inline-flex;
align-items: center;
gap: 0.25rem;
}
.qa-pass { background-color: #ecfdf5; color: #047857; border: 1px solid #a7f3d0; }
.qa-fail { background-color: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }
.qa-pending { background-color: #fffbeb; color: #b45309; border: 1px solid #fde68a; }
</style>
</head>
<body class="bg-gray-50 min-h-screen p-8 md:p-12">

<div id="app" class="max-w-7xl mx-auto">
<header class="mb-8 border-b-2 border-indigo-100 pb-4 flex justify-between items-center">
<div>
<h1 class="text-4xl font-extrabold text-indigo-800">倉庫作業明細</h1>
<p class="text-gray-500 text-md mt-1"></p>
</div>
<div class="text-right">
<span class="text-sm font-semibold text-indigo-600 bg-indigo-50 px-4 py-2 rounded-xl border border-indigo-100">
📅 資料時間:2026/07/15 09:15
</span>
</div>
</header>

<div class="bg-white rounded-3xl shadow-xl border border-gray-100 overflow-hidden p-6">
<div class="flex flex-col md:flex-row justify-between items-center gap-4 mb-6">
<div class="w-full md:w-80">
<input type="text" v-model="searchQuery" placeholder="搜尋單號、料號、品名..." class="w-full p-2.5 border border-gray-300 rounded-xl focus-ring text-sm">
</div>
<div class="text-sm font-medium text-gray-500">
共顯示 <span class="text-indigo-600 font-bold">{{ displayList.length }}</span> 筆待辦資料
</div>
</div>

<div class="overflow-x-auto shadow-sm rounded-2xl border border-gray-100">
<table class="min-w-full text-sm text-left">
<thead class="bg-gray-100 text-gray-700 font-semibold uppercase">
<tr>
<th class="p-4 rounded-l-xl">📌 作業類型</th>
<th class="p-4">相關單號</th>
<th class="p-4">料號 / 品名說明</th>
<th class="p-4 text-right">作業數量</th>
<th class="p-4 text-center rounded-r-xl">🧪 QC 檢驗結果</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100 bg-white">
<tr v-for="item in displayList" :key="item.id" class="hover:bg-gray-50 transition">
<td class="p-4">
<span :class="getTypeClass(item.taskType)" class="type-badge">
{{ item.taskType }}
</span>
</td>
<td class="p-4 font-mono font-medium text-gray-900">
{{ item.docNo }}
</td>
<td class="p-4">
<span class="font-semibold text-gray-900 block">{{ item.partNo }}</span>
<span class="text-xs text-gray-500">{{ item.partName }}</span>
</td>
<td class="p-4 text-right">
<span class="font-mono text-base font-bold text-gray-800">{{ item.quantity.toLocaleString() }}</span>
<span class="text-xs text-gray-500 ml-1">{{ item.unit }}</span>
</td>
<td class="p-4 text-center">
<template v-if="item.taskType === '待入庫'">
<span :class="getQaClass(item.qaResult)" class="qa-badge">
{{ item.qaResult }}
</span>
</template>
<template v-else>
<span class="text-gray-300 font-mono">-</span>
</template>
</td>
</tr>
<tr v-if="displayList.length === 0">
<td colspan="5" class="text-center py-12 text-gray-400 text-lg bg-gray-50">
沒有符合當前條件的物流單據。
</td>
</tr>
</tbody>
</table>
</div>

</div>
</div>

<script>
const { createApp, ref, computed } = Vue;

createApp({
setup() {
const searchQuery = ref('');

// 全局打散的流水帳假資料
const allItems = ref([
{ id: 1, taskType: '待入庫', docNo: 'MO-20260714-001', partNo: 'FG-DEVICE-005', partName: '智能感應器 V2.0', quantity: 400, unit: 'PCS', qaResult: '合格' },
{ id: 2, taskType: '待入庫', docNo: 'MO-20260714-002', partNo: 'SP-MODULE-01A', partName: '電源供應模組', quantity: 500, unit: 'SET', qaResult: '待檢' },
{ id: 3, taskType: '待出貨', docNo: 'SO-20260701-09', partNo: 'FG-DEVICE-005', partName: '智能感應器 V2.0', quantity: 200, unit: 'PCS', qaResult: '' },
{ id: 4, taskType: '待出貨', docNo: 'SO-20260702-14', partNo: 'FG-WIFI-010', partName: '工業級無線模組', quantity: 500, unit: 'PCS', qaResult: '' },
{ id: 5, taskType: '待發料', docNo: 'MO-20260716-001', partNo: 'RM-CHIP-882', partName: '主控 MCU 晶片', quantity: 1500, unit: 'PCS', qaResult: '' },
{ id: 6, taskType: '待發料', docNo: 'MO-20260716-001', partNo: 'RM-PCB-04', partName: '四層控制電路板', quantity: 1500, unit: 'PCS', qaResult: '' },
{ id: 7, taskType: '待收料', docNo: 'PO-20260630-01', partNo: 'RM-CONN-02', partName: '8-Pin 防水接插件', quantity: 1500, unit: 'PCS', qaResult: '' },
{ id: 8, taskType: '待收料', docNo: 'PO-20260702-05', partNo: 'RM-LED-RGB', partName: '高亮度 RGB 指示燈 bead', quantity: 20000, unit: 'PCS', qaResult: '' }
]);

// 類型顏色區分
const getTypeClass = (type) => {
if (type === '待入庫') return 'type-receipt';
if (type === '待出貨') return 'type-shipping';
if (type === '待發料') return 'type-mat-issue';
if (type === '待收料') return 'type-sup-receipt';
return '';
};

// QC 樣式對應
const getQaClass = (result) => {
if (result === '合格') return 'qa-pass';
if (result === '不合格') return 'qa-fail';
return 'qa-pending';
};

// 關鍵字模糊搜尋
const displayList = computed(() => {
const query = searchQuery.value.toLowerCase().trim();
if (!query) return allItems.value;

return allItems.value.filter(item => {
return item.docNo.toLowerCase().includes(query) ||
item.partNo.toLowerCase().includes(query) ||
item.partName.toLowerCase().includes(query) ||
item.taskType.toLowerCase().includes(query);
});
});

return {
searchQuery,
displayList,
getTypeClass,
getQaClass
};
}
}).mount('#app');
</script>
</body>
</html>
    (1-1/1)