FPSMS-frontend
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

ProductionProcessPage.tsx 6.2 KiB

3 meses atrás
3 meses atrás
3 meses atrás
2 meses atrás
3 meses atrás
3 meses atrás
3 meses atrás
3 meses atrás
3 meses atrás
3 meses atrás
3 meses atrás
2 meses atrás
3 meses atrás
2 meses atrás
2 meses atrás
2 meses atrás
2 meses atrás
3 meses atrás
3 meses atrás
3 meses atrás
3 meses atrás
3 meses atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. "use client";
  2. import React, { useState, useEffect, useCallback } from "react";
  3. import { useSession } from "next-auth/react";
  4. import { SessionWithTokens } from "@/config/authConfig";
  5. import { Box, Tabs, Tab, Stack, Typography, Autocomplete, TextField } from "@mui/material";
  6. import ProductionProcessList from "@/components/ProductionProcess/ProductionProcessList";
  7. import ProductionProcessDetail from "@/components/ProductionProcess/ProductionProcessDetail";
  8. import ProductionProcessJobOrderDetail from "@/components/ProductionProcess/ProductionProcessJobOrderDetail";
  9. import JobPickExecutionsecondscan from "@/components/Jodetail/JobPickExecutionsecondscan";
  10. import FinishedQcJobOrderList from "@/components/ProductionProcess/FinishedQcJobOrderList";
  11. import {
  12. fetchProductProcesses,
  13. fetchProductProcessesByJobOrderId,
  14. ProductProcessLineResponse
  15. } from "@/app/api/jo/actions";
  16. import { useTranslation } from "react-i18next";
  17. type PrinterCombo = {
  18. id: number;
  19. value: number;
  20. label?: string;
  21. code?: string;
  22. name?: string;
  23. description?: string;
  24. ip?: string;
  25. port?: number;
  26. };
  27. interface ProductionProcessPageProps {
  28. printerCombo: PrinterCombo[];
  29. }
  30. const STORAGE_KEY = 'productionProcess_selectedMatchingStock';
  31. const ProductionProcessPage: React.FC<ProductionProcessPageProps> = ({ printerCombo }) => {
  32. const { t } = useTranslation(["common"]);
  33. const [selectedProcessId, setSelectedProcessId] = useState<number | null>(null);
  34. const [selectedMatchingStock, setSelectedMatchingStock] = useState<{
  35. jobOrderId: number;
  36. productProcessId: number;
  37. } | null>(null);
  38. const [tabIndex, setTabIndex] = useState(0);
  39. const { data: session } = useSession() as { data: SessionWithTokens | null };
  40. const currentUserId = session?.id ? parseInt(session.id) : undefined;
  41. // Add printer selection state
  42. const [selectedPrinter, setSelectedPrinter] = useState<PrinterCombo | null>(
  43. printerCombo && printerCombo.length > 0 ? printerCombo[0] : null
  44. );
  45. // 从 sessionStorage 恢复状态(仅在客户端)
  46. useEffect(() => {
  47. if (typeof window !== 'undefined') {
  48. try {
  49. const saved = sessionStorage.getItem(STORAGE_KEY);
  50. if (saved) {
  51. const parsed = JSON.parse(saved);
  52. // 验证数据有效性
  53. if (parsed && typeof parsed.jobOrderId === 'number' && typeof parsed.productProcessId === 'number') {
  54. setSelectedMatchingStock(parsed);
  55. console.log(" Restored selectedMatchingStock from sessionStorage:", parsed);
  56. }
  57. }
  58. } catch (error) {
  59. console.error("Error restoring selectedMatchingStock:", error);
  60. sessionStorage.removeItem(STORAGE_KEY);
  61. }
  62. }
  63. }, []);
  64. // 保存状态到 sessionStorage
  65. useEffect(() => {
  66. if (typeof window !== 'undefined') {
  67. if (selectedMatchingStock) {
  68. sessionStorage.setItem(STORAGE_KEY, JSON.stringify(selectedMatchingStock));
  69. console.log(" Saved selectedMatchingStock to sessionStorage:", selectedMatchingStock);
  70. } else {
  71. sessionStorage.removeItem(STORAGE_KEY);
  72. }
  73. }
  74. }, [selectedMatchingStock]);
  75. // 处理返回列表时清除存储
  76. const handleBackFromSecondScan = useCallback(() => {
  77. setSelectedMatchingStock(null);
  78. if (typeof window !== 'undefined') {
  79. sessionStorage.removeItem(STORAGE_KEY);
  80. }
  81. }, []);
  82. const handleTabChange = useCallback((event: React.SyntheticEvent, newValue: number) => {
  83. setTabIndex(newValue);
  84. }, []);
  85. if (selectedMatchingStock) {
  86. return (
  87. <JobPickExecutionsecondscan
  88. filterArgs={{ jobOrderId: selectedMatchingStock.jobOrderId }}
  89. onBack={handleBackFromSecondScan}
  90. />
  91. );
  92. }
  93. if (selectedProcessId !== null) {
  94. return (
  95. <ProductionProcessJobOrderDetail
  96. jobOrderId={selectedProcessId}
  97. onBack={() => setSelectedProcessId(null)}
  98. />
  99. );
  100. }
  101. return (
  102. <Box>
  103. {/* Header section with printer selection */}
  104. {tabIndex === 1 && (
  105. <Box sx={{
  106. p: 1,
  107. borderBottom: '1px solid #e0e0e0',
  108. minHeight: 'auto',
  109. display: 'flex',
  110. alignItems: 'center',
  111. justifyContent: 'flex-end',
  112. gap: 2,
  113. flexWrap: 'wrap',
  114. }}>
  115. <Stack
  116. direction="row"
  117. spacing={2}
  118. sx={{
  119. alignItems: 'center',
  120. flexWrap: 'wrap',
  121. rowGap: 1,
  122. }}
  123. >
  124. <Typography variant="body2" sx={{ minWidth: 'fit-content', mr: 1.5 }}>
  125. {t("Select Printer")}:
  126. </Typography>
  127. <Autocomplete
  128. disableClearable
  129. options={printerCombo || []}
  130. getOptionLabel={(option) =>
  131. option.name || option.label || option.code || `Printer ${option.id}`
  132. }
  133. value={selectedPrinter || undefined}
  134. onChange={(_, newValue) => setSelectedPrinter(newValue)}
  135. sx={{ minWidth: 200 }}
  136. size="small"
  137. renderInput={(params) => (
  138. <TextField
  139. {...params}
  140. placeholder={t("Printer")}
  141. inputProps={{
  142. ...params.inputProps,
  143. readOnly: true,
  144. }}
  145. />
  146. )}
  147. />
  148. </Stack>
  149. </Box>
  150. )}
  151. <Tabs value={tabIndex} onChange={handleTabChange} sx={{ mb: 2 }}>
  152. <Tab label={t("Production Process")} />
  153. <Tab label={t("Finished QC Job Orders")} />
  154. </Tabs>
  155. {tabIndex === 0 && (
  156. <ProductionProcessList
  157. printerCombo={printerCombo}
  158. onSelectProcess={(jobOrderId) => {
  159. const id = jobOrderId ?? null;
  160. if (id !== null) {
  161. setSelectedProcessId(id);
  162. }
  163. }}
  164. onSelectMatchingStock={(jobOrderId, productProcessId) => {
  165. setSelectedMatchingStock({
  166. jobOrderId: jobOrderId || 0,
  167. productProcessId: productProcessId || 0
  168. });
  169. }}
  170. />
  171. )}
  172. {tabIndex === 1 && (
  173. <FinishedQcJobOrderList
  174. printerCombo={printerCombo}
  175. selectedPrinter={selectedPrinter}
  176. />
  177. )}
  178. </Box>
  179. );
  180. };
  181. export default ProductionProcessPage;