519 lines
14 KiB
Markdown
519 lines
14 KiB
Markdown
|
|
# Code128 條碼功能實作文件
|
|||
|
|
|
|||
|
|
## 📋 功能概述
|
|||
|
|
|
|||
|
|
已成功為甜點店 ERP 系統的商品建檔管理模組實作完整的 Code128 條碼功能,包含自動生成商品編號、條碼生成、預覽、下載與列印功能。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🗂️ 資料結構設計
|
|||
|
|
|
|||
|
|
### Product 介面(已更新)
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
export interface Product {
|
|||
|
|
id: string; // 系統內部 ID
|
|||
|
|
product_code: string; // 商品編號(系統自動生成,格式:ICE000001)
|
|||
|
|
name: string; // 商品名稱
|
|||
|
|
type: ProductType; // 類型(原物料/成品)
|
|||
|
|
category: string; // 分類
|
|||
|
|
unit: ProductUnit; // 單位
|
|||
|
|
barcode_value: string; // 條碼內容(預設等於商品編號)
|
|||
|
|
stockQuantity: number; // 庫存數量
|
|||
|
|
createdAt: string; // 建立日期
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 商品編號規則
|
|||
|
|
|
|||
|
|
- **格式**:`ICE` + 6位數字(例如:ICE000001、ICE000245)
|
|||
|
|
- **生成邏輯**:自動遞增,系統找出最大序號後 +1
|
|||
|
|
- **唯一性**:每個商品編號保證唯一
|
|||
|
|
- **用途**:作為條碼內容的預設值
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 UI 設計與 Wireframe
|
|||
|
|
|
|||
|
|
### 商品對話框結構
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────┐
|
|||
|
|
│ 編輯商品 / 新增商品 │
|
|||
|
|
├─────────────────────────────────────────────────┤
|
|||
|
|
│ │
|
|||
|
|
│ ┌─────────────────────────────────────────┐ │
|
|||
|
|
│ │ 商品編號: ICE000001 │ │ ← 商品編號區(僅編輯時顯示)
|
|||
|
|
│ │ 系統自動生成,不可修改 │ │
|
|||
|
|
│ └─────────────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ 商品名稱 * 類型 * │
|
|||
|
|
│ [__________] [原物料 ▼] │
|
|||
|
|
│ │
|
|||
|
|
│ 分類 * 單位 * │
|
|||
|
|
│ [__________] [公斤 ▼] │
|
|||
|
|
│ │
|
|||
|
|
│ 庫存數量 │
|
|||
|
|
│ [__________] │
|
|||
|
|
│ │
|
|||
|
|
│ ┌─────────────────────────────────────────┐ │
|
|||
|
|
│ │ 條碼資訊 │ │ ← 條碼區
|
|||
|
|
│ │ │ │
|
|||
|
|
│ │ 條碼內容 │ │
|
|||
|
|
│ │ [ICE000001_________] [🔄 重新生成] │ │
|
|||
|
|
│ │ 條碼內容預設等於商品編號... │ │
|
|||
|
|
│ │ │ │
|
|||
|
|
│ │ 條碼預覽 (Code128) │ │
|
|||
|
|
│ │ ┌───────────────────────────────────┐ │ │
|
|||
|
|
│ │ │ ║│││││││││││││││││││││││║ │ │ │
|
|||
|
|
│ │ │ ICE000001 │ │ │
|
|||
|
|
│ │ └───────────────────────────────────┘ │ │
|
|||
|
|
│ │ │ │
|
|||
|
|
│ │ [⬇️ 下載條碼圖片] [🖨️ 列印條碼標籤] │ │
|
|||
|
|
│ └─────────────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ [取消] [儲存變更] │
|
|||
|
|
└─────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 條碼區功能說明
|
|||
|
|
|
|||
|
|
1. **商品編號顯示**(僅編輯模式)
|
|||
|
|
- 藍色背景區塊
|
|||
|
|
- 顯示格式化的商品編號
|
|||
|
|
- 註明「系統自動生成,不可修改」
|
|||
|
|
|
|||
|
|
2. **條碼內容**
|
|||
|
|
- 顯示當前條碼值
|
|||
|
|
- 唯讀輸入框,等寬字體顯示
|
|||
|
|
- 「重新生成」按鈕:將條碼值恢復為商品編號
|
|||
|
|
|
|||
|
|
3. **條碼預覽**
|
|||
|
|
- 使用 Code128 格式
|
|||
|
|
- 白色背景,虛線邊框
|
|||
|
|
- 自動即時更新
|
|||
|
|
- 新增模式提示「條碼將在儲存後顯示」
|
|||
|
|
|
|||
|
|
4. **操作按鈕**
|
|||
|
|
- 下載條碼圖片(PNG 格式)
|
|||
|
|
- 列印條碼標籤(包含商品資訊)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔧 技術實作
|
|||
|
|
|
|||
|
|
### 使用的套件
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import JsBarcode from "jsbarcode";
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 核心組件
|
|||
|
|
|
|||
|
|
#### 1. BarcodeDisplay 組件
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// /components/BarcodeDisplay.tsx
|
|||
|
|
// 功能:使用 JsBarcode 生成 Code128 條碼
|
|||
|
|
// 參數:value, width, height, displayValue
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2. ProductDialog 組件更新
|
|||
|
|
|
|||
|
|
**主要新增功能:**
|
|||
|
|
- 商品編號顯示區域
|
|||
|
|
- 條碼內容輸入框(唯讀)
|
|||
|
|
- 條碼預覽區域
|
|||
|
|
- 重新生成按鈕
|
|||
|
|
- 下載與列印功能
|
|||
|
|
|
|||
|
|
#### 3. ProductManagement 組件更新
|
|||
|
|
|
|||
|
|
**新增函數:**
|
|||
|
|
```typescript
|
|||
|
|
generateProductCode(): string
|
|||
|
|
```
|
|||
|
|
- 自動生成下一個商品編號
|
|||
|
|
- 確保唯一性
|
|||
|
|
- 格式:ICE + 6位數字
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔄 業務邏輯流程
|
|||
|
|
|
|||
|
|
### 新增商品流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 使用者點擊「新增商品」
|
|||
|
|
↓
|
|||
|
|
2. 填寫商品基本資料(名稱、類型、分類等)
|
|||
|
|
↓
|
|||
|
|
3. 條碼區顯示「條碼將在儲存後顯示」
|
|||
|
|
↓
|
|||
|
|
4. 點擊「新增商品」
|
|||
|
|
↓
|
|||
|
|
5. 系統自動生成 product_code (例:ICE000007)
|
|||
|
|
↓
|
|||
|
|
6. barcode_value 自動設為 product_code
|
|||
|
|
↓
|
|||
|
|
7. 商品儲存完成,可再次編輯查看條碼
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 編輯商品流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 使用者點擊「編輯」按鈕
|
|||
|
|
↓
|
|||
|
|
2. 對話框顯示商品編號(藍色區塊)
|
|||
|
|
↓
|
|||
|
|
3. 條碼區顯示當前條碼值與 Code128 條碼圖
|
|||
|
|
↓
|
|||
|
|
4. 可選操作:
|
|||
|
|
- 重新生成條碼(恢復為商品編號)
|
|||
|
|
- 下載條碼圖片
|
|||
|
|
- 列印條碼標籤
|
|||
|
|
↓
|
|||
|
|
5. 修改其他資料後儲存
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 重新生成條碼
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 點擊「重新生成條碼」按鈕
|
|||
|
|
↓
|
|||
|
|
2. barcode_value 更新為 product_code
|
|||
|
|
↓
|
|||
|
|
3. 條碼圖自動重新渲染
|
|||
|
|
↓
|
|||
|
|
4. 顯示成功提示訊息
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 下載條碼圖片
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 點擊「下載條碼圖片」
|
|||
|
|
↓
|
|||
|
|
2. 從 Canvas 取得條碼圖片
|
|||
|
|
↓
|
|||
|
|
3. 轉換為 PNG 格式
|
|||
|
|
↓
|
|||
|
|
4. 觸發瀏覽器下載
|
|||
|
|
↓
|
|||
|
|
5. 檔名:barcode-ICE000001.png
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 列印條碼標籤
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 點擊「列印條碼標籤」
|
|||
|
|
↓
|
|||
|
|
2. 開啟新視窗
|
|||
|
|
↓
|
|||
|
|
3. 顯示條碼圖 + 商品資訊
|
|||
|
|
- 商品名稱
|
|||
|
|
- 商品編號
|
|||
|
|
↓
|
|||
|
|
4. 自動觸發列印對話框
|
|||
|
|
↓
|
|||
|
|
5. 列印完成後關閉視窗
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 使用情境範例
|
|||
|
|
|
|||
|
|
### 情境 1:新增新商品「芒果刨冰」
|
|||
|
|
|
|||
|
|
1. 店員點擊「新增商品」
|
|||
|
|
2. 輸入商品資料:
|
|||
|
|
- 名稱:芒果刨冰
|
|||
|
|
- 類型:成品
|
|||
|
|
- 分類:冰品
|
|||
|
|
- 單位:個
|
|||
|
|
3. 點擊「新增商品」儲存
|
|||
|
|
4. 系統自動生成:
|
|||
|
|
- product_code: ICE000245
|
|||
|
|
- barcode_value: ICE000245
|
|||
|
|
5. 商品建立完成,可在倉庫撿貨與 POS 掃碼使用
|
|||
|
|
|
|||
|
|
### 情境 2:商品編號需要恢復
|
|||
|
|
|
|||
|
|
1. 某次誤操作後,條碼內容被意外修改
|
|||
|
|
2. 管理者進入「編輯商品」
|
|||
|
|
3. 看到條碼值與商品編號不一致
|
|||
|
|
4. 點擊「重新生成條碼」
|
|||
|
|
5. 系統將 barcode_value 重置為 product_code
|
|||
|
|
6. 條碼恢復正常,可重新列印標籤
|
|||
|
|
|
|||
|
|
### 情境 3:列印商品標籤
|
|||
|
|
|
|||
|
|
1. 倉庫收到新的原物料「法國麵粉」
|
|||
|
|
2. 管理者編輯該商品資料
|
|||
|
|
3. 點擊「列印條碼標籤」
|
|||
|
|
4. 列印對話框顯示條碼與商品資訊
|
|||
|
|
5. 連接標籤機或一般印表機列印
|
|||
|
|
6. 將標籤貼在商品包裝上
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔐 權限與錯誤處理
|
|||
|
|
|
|||
|
|
### 權限控管
|
|||
|
|
|
|||
|
|
1. **商品編號修改**
|
|||
|
|
- 目前設定:不可修改(唯讀)
|
|||
|
|
- 未來擴充:可設定管理員權限允許修改
|
|||
|
|
|
|||
|
|
2. **條碼重新生成**
|
|||
|
|
- 所有可編輯商品的使用者皆可使用
|
|||
|
|
- 建議:可加入操作記錄追蹤
|
|||
|
|
|
|||
|
|
### 錯誤處理
|
|||
|
|
|
|||
|
|
#### 1. 條碼生成失敗
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// BarcodeDisplay 組件已處理
|
|||
|
|
try {
|
|||
|
|
JsBarcode(canvasRef.current, value, {...});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error("Error generating barcode:", error);
|
|||
|
|
// 顯示友善錯誤訊息
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**可能原因:**
|
|||
|
|
- 條碼內容包含無效字符
|
|||
|
|
- Code128 不支援的特殊符號
|
|||
|
|
|
|||
|
|
**解決方案:**
|
|||
|
|
- 確保商品編號僅包含英數字
|
|||
|
|
- 顯示錯誤提示給使用者
|
|||
|
|
|
|||
|
|
#### 2. 條碼重複檢查
|
|||
|
|
|
|||
|
|
**目前實作:**
|
|||
|
|
- 商品編號自動遞增,保證唯一性
|
|||
|
|
- barcode_value 預設等於 product_code
|
|||
|
|
|
|||
|
|
**未來建議:**
|
|||
|
|
```typescript
|
|||
|
|
// 儲存前檢查條碼重複
|
|||
|
|
const isDuplicate = products.some(
|
|||
|
|
p => p.barcode_value === formData.barcode_value && p.id !== product?.id
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (isDuplicate) {
|
|||
|
|
toast.error("條碼內容重複,請重新生成");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3. 下載/列印失敗
|
|||
|
|
|
|||
|
|
**處理方式:**
|
|||
|
|
- 檢查 Canvas 元素是否存在
|
|||
|
|
- 瀏覽器權限檢查
|
|||
|
|
- 顯示友善錯誤訊息
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 商品列表更新
|
|||
|
|
|
|||
|
|
### 新增欄位
|
|||
|
|
|
|||
|
|
商品列表已更新,新增「商品編號」欄位:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
| 商品編號 | 商品名稱 | 類型 | 分類 | 條碼 | 單位 | 庫存數量 | 操作 |
|
|||
|
|
|-----------|-------------|--------|---------|-----------|------|----------|------|
|
|||
|
|
| ICE000001 | 法國麵粉 | 原物料 | 烘焙材料 | ICE000001 | 公斤 | 150 | ✏️🗑️ |
|
|||
|
|
| ICE000002 | 草莓蛋糕 | 成品 | 蛋糕 | ICE000002 | 個 | - | ✏️🗑️ |
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 搜尋功能更新
|
|||
|
|
|
|||
|
|
搜尋框已支援商品編號搜尋:
|
|||
|
|
- 商品名稱
|
|||
|
|
- **商品編號(新增)**
|
|||
|
|
- 條碼內容
|
|||
|
|
- 分類
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🚀 未來擴充建議
|
|||
|
|
|
|||
|
|
### 1. 批次條碼列印
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 選擇多個商品,一次列印所有條碼標籤
|
|||
|
|
const handleBatchPrint = (selectedProducts: Product[]) => {
|
|||
|
|
// 生成包含多個條碼的列印頁面
|
|||
|
|
// 適合一次收貨多種商品的情境
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 自訂條碼規則
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 允許管理員自訂商品編號前綴
|
|||
|
|
interface BarcodeSettings {
|
|||
|
|
prefix: string; // 例:ICE, CAKE, RAW
|
|||
|
|
digitLength: number; // 例:6
|
|||
|
|
startNumber: number; // 例:1
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 條碼掃描驗證
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 使用手機或掃碼槍掃描條碼
|
|||
|
|
// 驗證條碼是否存在於系統中
|
|||
|
|
const handleBarcodeScan = (scannedValue: string) => {
|
|||
|
|
const product = products.find(p => p.barcode_value === scannedValue);
|
|||
|
|
if (product) {
|
|||
|
|
// 顯示商品詳情
|
|||
|
|
} else {
|
|||
|
|
// 提示條碼不存在
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 條碼操作記錄
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface BarcodeLog {
|
|||
|
|
productId: string;
|
|||
|
|
action: 'generated' | 'regenerated' | 'printed' | 'downloaded';
|
|||
|
|
oldValue?: string;
|
|||
|
|
newValue: string;
|
|||
|
|
timestamp: string;
|
|||
|
|
userId: string;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. QR Code 支援
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 除了 Code128,也支援 QR Code
|
|||
|
|
// QR Code 可包含更多資訊(URL、JSON 等)
|
|||
|
|
import QRCode from "qrcode";
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📝 測試檢查清單
|
|||
|
|
|
|||
|
|
- [x] 新增商品時自動生成商品編號
|
|||
|
|
- [x] barcode_value 預設等於 product_code
|
|||
|
|
- [x] Code128 條碼正確生成並顯示
|
|||
|
|
- [x] 重新生成條碼功能正常
|
|||
|
|
- [x] 下載條碼圖片功能正常
|
|||
|
|
- [x] 列印條碼標籤功能正常
|
|||
|
|
- [x] 商品編號在編輯時唯讀顯示
|
|||
|
|
- [x] 商品列表顯示商品編號
|
|||
|
|
- [x] 搜尋支援商品編號
|
|||
|
|
- [x] 條碼生成錯誤處理
|
|||
|
|
- [x] UI 符合 Guidelines 設計規範
|
|||
|
|
- [x] 響應式設計(桌面版)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 設計規範遵循
|
|||
|
|
|
|||
|
|
根據 Guidelines.md:
|
|||
|
|
|
|||
|
|
1. **主要動作按鈕**
|
|||
|
|
- 「新增商品」:使用 `button-filled-primary`
|
|||
|
|
- 「儲存變更」:使用 `button-filled-primary`
|
|||
|
|
|
|||
|
|
2. **次要動作按鈕**
|
|||
|
|
- 「取消」:使用 `button-outlined-primary`
|
|||
|
|
- 「重新生成」:使用 `button-outlined-primary`
|
|||
|
|
- 「下載條碼圖片」:使用 `button-outlined-primary`
|
|||
|
|
- 「列印條碼標籤」:使用 `button-outlined-primary`
|
|||
|
|
|
|||
|
|
3. **對比度檢查**
|
|||
|
|
- 所有按鈕的背景色與文字色皆符合對比度要求
|
|||
|
|
- 使用 CSS 變數確保一致性
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📚 相關檔案清單
|
|||
|
|
|
|||
|
|
### 新增檔案
|
|||
|
|
- `/components/BarcodeDisplay.tsx` - 條碼顯示組件
|
|||
|
|
|
|||
|
|
### 修改檔案
|
|||
|
|
- `/components/ProductManagement.tsx` - 新增商品編號生成邏輯
|
|||
|
|
- `/components/ProductDialog.tsx` - 新增條碼區域與相關功能
|
|||
|
|
- `/components/ProductTable.tsx` - 新增商品編號欄位
|
|||
|
|
|
|||
|
|
### 參考檔案
|
|||
|
|
- `/styles/globals.css` - 按鈕與樣式定義
|
|||
|
|
- `/guidelines/Guidelines.md` - 設計規範
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 💡 使用建議
|
|||
|
|
|
|||
|
|
1. **定期備份商品資料**
|
|||
|
|
- 商品編號與條碼資訊非常重要
|
|||
|
|
- 建議定期匯出資料
|
|||
|
|
|
|||
|
|
2. **標籤管理**
|
|||
|
|
- 建議使用熱感應標籤紙
|
|||
|
|
- 條碼尺寸適合一般掃碼槍讀取
|
|||
|
|
|
|||
|
|
3. **倉庫作業流程**
|
|||
|
|
- 收貨時列印標籤並貼在商品上
|
|||
|
|
- 撿貨時掃描條碼確認商品
|
|||
|
|
- POS 結帳時掃描條碼計價
|
|||
|
|
|
|||
|
|
4. **條碼品質**
|
|||
|
|
- 確保列印清晰
|
|||
|
|
- 避免條碼損壞或污損
|
|||
|
|
- 定期更換磨損的標籤
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔧 故障排除
|
|||
|
|
|
|||
|
|
### 問題 1:條碼無法顯示
|
|||
|
|
|
|||
|
|
**可能原因:**
|
|||
|
|
- JsBarcode 套件未正確載入
|
|||
|
|
- 條碼內容包含無效字符
|
|||
|
|
|
|||
|
|
**解決方式:**
|
|||
|
|
- 檢查控制台錯誤訊息
|
|||
|
|
- 確認條碼內容僅包含英數字
|
|||
|
|
|
|||
|
|
### 問題 2:列印視窗空白
|
|||
|
|
|
|||
|
|
**可能原因:**
|
|||
|
|
- 瀏覽器阻擋彈出視窗
|
|||
|
|
- Canvas 尚未完成渲染
|
|||
|
|
|
|||
|
|
**解決方式:**
|
|||
|
|
- 允許瀏覽器彈出視窗
|
|||
|
|
- 確認條碼已正確顯示後再列印
|
|||
|
|
|
|||
|
|
### 問題 3:商品編號重複
|
|||
|
|
|
|||
|
|
**可能原因:**
|
|||
|
|
- 多個使用者同時新增商品
|
|||
|
|
- 資料同步問題
|
|||
|
|
|
|||
|
|
**解決方式:**
|
|||
|
|
- 使用資料庫自動遞增序號
|
|||
|
|
- 實作樂觀鎖定機制
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📞 技術支援
|
|||
|
|
|
|||
|
|
如有任何問題或建議,請聯繫開發團隊。
|
|||
|
|
|
|||
|
|
最後更新:2025-11-28
|