Просмотр исходного кода

update of qr-code of user

master
LAPTOP-EU9T8H5F\User 12 часов назад
Родитель
Сommit
0c3636f227
4 измененных файлов: 174 добавлений и 76 удалений
  1. +1
    -0
      src/app/api/settings/printer/index.ts
  2. +171
    -74
      src/components/qrCodeHandles/qrCodeHandleSearch.tsx
  3. +1
    -1
      src/i18n/zh/common.json
  4. +1
    -1
      src/i18n/zh/jo.json

+ 1
- 0
src/app/api/settings/printer/index.ts Просмотреть файл

@@ -9,6 +9,7 @@ export interface PrinterCombo {
label?: string;
code?: string;
name?: string;
type?: string;
description?: string;
ip?: string;
port?: number;


+ 171
- 74
src/components/qrCodeHandles/qrCodeHandleSearch.tsx Просмотреть файл

@@ -13,7 +13,25 @@ import { UserResult } from "@/app/api/user";
import { deleteUser } from "@/app/api/user/actions";
import QrCodeIcon from "@mui/icons-material/QrCode";
import { exportUserQrCode } from "@/app/api/user/client";
import { Checkbox, Box, Button, TextField, Stack, Autocomplete, Modal, Card, IconButton } from "@mui/material";
import {
Checkbox,
Box,
Button,
TextField,
Stack,
Autocomplete,
Modal,
Card,
IconButton,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
Typography
} from "@mui/material";
import DownloadIcon from "@mui/icons-material/Download";
import PrintIcon from "@mui/icons-material/Print";
import CloseIcon from "@mui/icons-material/Close";
@@ -41,23 +59,15 @@ const QrCodeHandleSearch: React.FC<Props> = ({ users, printerCombo }) => {
const [selectAll, setSelectAll] = useState(false);
const [printQty, setPrintQty] = useState(1);

// Preview modal state
const [previewOpen, setPreviewOpen] = useState(false);
const [previewUrl, setPreviewUrl] = useState<string | null>(null);

const [selectedUsersModalOpen, setSelectedUsersModalOpen] = useState(false);

const filteredPrinters = useMemo(() => {
const allowedPrinterNames = [
"A4印機 測試用 Local",
"A4印機 測試用 Server",
"A4 2F Office",
"A4 2F 雪庫",
];
return printerCombo.filter((printer) => {
const printerName = printer.name || printer.label || printer.code || "";
return allowedPrinterNames.includes(printerName);
});
return printerCombo.filter((printer) => {
return printer.type === "A4";
});
}, [printerCombo]);

const [selectedPrinter, setSelectedPrinter] = useState<PrinterCombo | undefined>(
@@ -150,7 +160,8 @@ const QrCodeHandleSearch: React.FC<Props> = ({ users, printerCombo }) => {
setIsUploading(true);
const response = await exportUserQrCode(userIds);
downloadFile(response.blobValue, response.filename);
successDialog(t("QR Code exported successfully"), t);
setSelectedUsersModalOpen(false);
successDialog("二維碼已下載", t);
} catch (error) {
console.error("Error exporting QR code:", error);
} finally {
@@ -183,16 +194,29 @@ const QrCodeHandleSearch: React.FC<Props> = ({ users, printerCombo }) => {
setTimeout(() => {
URL.revokeObjectURL(url);
}, 1000);
setSelectedUsersModalOpen(false);
successDialog("二維碼已列印", t);
} catch (error) {
console.error("Error printing QR code:", error);
} finally {
setIsUploading(false);
}
}, [checkboxIds, printQty, setIsUploading]);
}, [checkboxIds, printQty, setIsUploading, t]);

const handleViewSelectedQrCodes = useCallback(() => {
if (checkboxIds.length === 0) {
return;
}
setSelectedUsersModalOpen(true);
}, [checkboxIds]);

const selectedUsers = useMemo(() => {
return users.filter(user => checkboxIds.includes(user.id));
}, [users, checkboxIds]);

const handleViewSelectedQrCodes = useCallback(async () => {
await handleDownloadQrCode(checkboxIds);
}, [checkboxIds, handleDownloadQrCode]);
const handleCloseSelectedUsersModal = useCallback(() => {
setSelectedUsersModalOpen(false);
}, []);

const columns = useMemo<Column<UserResult>[]>(
() => [
@@ -263,7 +287,6 @@ const QrCodeHandleSearch: React.FC<Props> = ({ users, printerCombo }) => {
totalCount={filteredUser.length}
isAutoPaging={true}
/>
{/* Add select all and view selected buttons */}
<Box sx={{ mb: 2, display: 'flex', alignItems: 'center', gap: 2 }}>
<Button
variant="outlined"
@@ -282,67 +305,143 @@ const QrCodeHandleSearch: React.FC<Props> = ({ users, printerCombo }) => {
</Button>
</Box>

{/* Print and Download Section */}
<Box
<Modal
open={selectedUsersModalOpen}
onClose={handleCloseSelectedUsersModal}
sx={{
p: 2,
borderTop: 1,
borderColor: 'divider',
bgcolor: 'background.paper',
mt: 2,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Stack direction="row" justifyContent="flex-end" alignItems="center" gap={2}>
<Autocomplete<PrinterCombo>
options={filteredPrinters}
value={selectedPrinter ?? null}
onChange={(event, value) => {
setSelectedPrinter(value ?? undefined);
<Card
sx={{
position: 'relative',
width: '90%',
maxWidth: '800px',
maxHeight: '90vh',
display: 'flex',
flexDirection: 'column',
outline: 'none',
}}
>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
p: 2,
borderBottom: 1,
borderColor: 'divider',
}}
getOptionLabel={(option) => option.name || option.label || option.code || String(option.id)}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
label="列印機"
sx={{ width: 300 }}
/>
)}
/>
<TextField
variant="outlined"
label="列印數量"
type="number"
value={printQty}
onChange={(e) => {
const value = parseInt(e.target.value) || 1;
setPrintQty(Math.max(1, value));
>
<Typography variant="h6" component="h2">
已選擇用戶 ({selectedUsers.length})
</Typography>
<IconButton onClick={handleCloseSelectedUsersModal}>
<CloseIcon />
</IconButton>
</Box>

<Box
sx={{
flex: 1,
overflow: 'auto',
p: 2,
}}
inputProps={{ min: 1 }}
sx={{ width: 120 }}
/>
<Button
variant="contained"
startIcon={<PrintIcon />}
onClick={handlePrint}
disabled={checkboxIds.length === 0 || filteredPrinters.length === 0}
color="primary"
>
列印
</Button>
<Button
variant="contained"
startIcon={<DownloadIcon />}
onClick={handleViewSelectedQrCodes}
disabled={checkboxIds.length === 0}
color="primary"
<TableContainer component={Paper} variant="outlined">
<Table>
<TableHead>
<TableRow>
<TableCell>
<strong>{t("Username")}</strong>
</TableCell>
<TableCell>
<strong>{t("staffNo")}</strong>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{selectedUsers.length === 0 ? (
<TableRow>
<TableCell colSpan={2} align="center">
沒有選擇的用戶
</TableCell>
</TableRow>
) : (
selectedUsers.map((user) => (
<TableRow key={user.id}>
<TableCell>{user.username || '-'}</TableCell>
<TableCell>{user.staffNo || '-'}</TableCell>
</TableRow>
))
)}
</TableBody>
</Table>
</TableContainer>
</Box>

<Box
sx={{
p: 2,
borderTop: 1,
borderColor: 'divider',
bgcolor: 'background.paper',
}}
>
下載QR碼
</Button>
</Stack>
</Box>
<Stack direction="row" justifyContent="flex-end" alignItems="center" gap={2}>
<Autocomplete<PrinterCombo>
options={filteredPrinters}
value={selectedPrinter ?? null}
onChange={(event, value) => {
setSelectedPrinter(value ?? undefined);
}}
getOptionLabel={(option) => option.name || option.label || option.code || String(option.id)}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
label="列印機"
sx={{ width: 300 }}
/>
)}
/>
<TextField
variant="outlined"
label="列印數量"
type="number"
value={printQty}
onChange={(e) => {
const value = parseInt(e.target.value) || 1;
setPrintQty(Math.max(1, value));
}}
inputProps={{ min: 1 }}
sx={{ width: 120 }}
/>
<Button
variant="contained"
startIcon={<PrintIcon />}
onClick={handlePrint}
disabled={checkboxIds.length === 0 || filteredPrinters.length === 0}
color="primary"
>
列印
</Button>
<Button
variant="contained"
startIcon={<DownloadIcon />}
onClick={() => handleDownloadQrCode(checkboxIds)}
disabled={checkboxIds.length === 0}
color="primary"
>
下載QR碼
</Button>
</Stack>
</Box>
</Card>
</Modal>

{/* PDF Preview Modal - Simple preview only */}
<Modal
open={previewOpen}
onClose={handleClosePreview}
@@ -363,7 +462,6 @@ const QrCodeHandleSearch: React.FC<Props> = ({ users, printerCombo }) => {
outline: 'none',
}}
>
{/* Header with close button only */}
<Box
sx={{
display: 'flex',
@@ -381,7 +479,6 @@ const QrCodeHandleSearch: React.FC<Props> = ({ users, printerCombo }) => {
</IconButton>
</Box>

{/* PDF Preview */}
<Box
sx={{
flex: 1,


+ 1
- 1
src/i18n/zh/common.json Просмотреть файл

@@ -113,7 +113,7 @@
"QC Category":"QC品檢模板",
"qcCategory":"品檢模板",
"QC Check Template":"QC檢查模板",
"QR Code Handle":"二維碼處理",
"QR Code Handle":"二維碼列印及下載",
"Mail":"郵件",
"Import Testing":"匯入測試",
"Overview": "總覽",


+ 1
- 1
src/i18n/zh/jo.json Просмотреть файл

@@ -446,7 +446,7 @@
"QC Category":"QC品檢模板",
"qcCategory":"品檢模板",
"QC Check Template":"QC檢查模板",
"QR Code Handle":"二維碼處理",
"QR Code Handle":"二維碼列印及下載",
"Mail":"郵件",
"Import Testing":"匯入測試",
"Overview": "總覽",


Загрузка…
Отмена
Сохранить