| | |
| | | import { ref, onMounted, onUnmounted } from 'vue'; |
| | | import { ref, onMounted, computed } from 'vue'; |
| | | |
| | | // Interfaces mapping from Delphi structures |
| | | interface TPoint { |
| | | X: number; |
| | | Y: number; |
| | | } |
| | | |
| | | interface TErrListItem { |
| | | content: string; |
| | | interface ErrItem { |
| | | reason: string; |
| | | index: string; |
| | | } |
| | | |
| | | export function useErrListLogic() { |
| | | // State from Delphi variables |
| | | const errListItems = ref<TErrListItem[]>([ |
| | | // Mock data for display |
| | | { content: '測試錯誤原因1', index: 'Item_1' }, |
| | | { content: '測試錯誤原因2', index: 'Item_2' } |
| | | ]); |
| | | const selectedItemIndex = ref<number>(-1); |
| | | // --- State Mapped from Delphi UI Components --- |
| | | |
| | | const errorItems = ref<ErrItem[]>([]); |
| | | const selectedIndex = ref<number>(-1); |
| | | |
| | | const primaryImage = ref<string>(''); |
| | | const relatedImage = ref<string>(''); |
| | | |
| | | const siteIdx = ref<number>(1); |
| | | const siteCount = ref<number>(0); |
| | | const relaSiteIdx = ref<number>(1); |
| | | const relaSiteCount = ref<number>(0); |
| | | |
| | | const isDeleteEnabled = ref<boolean>(false); |
| | | const isImmediateEnabled = ref<boolean>(false); |
| | | |
| | | const siteIndex = ref<number>(0); |
| | | const siteTotal = ref<number>(0); |
| | | const isSitePreEnabled = ref<boolean>(false); |
| | | const isSiteNextEnabled = ref<boolean>(false); |
| | | const SiteList = ref<string[]>([]); // TStringlist |
| | | // --- Methods --- |
| | | |
| | | const relaSiteIndex = ref<number>(0); |
| | | const relaSiteTotal = ref<number>(0); |
| | | const isRelaPreEnabled = ref<boolean>(false); |
| | | const isRelaNextEnabled = ref<boolean>(false); |
| | | const RelaSiteList = ref<string[]>([]); // TStringlist |
| | | const FormCreate = () => { |
| | | console.log('ErrlistForm created'); |
| | | // Mock initialization |
| | | errorItems.value = [ |
| | | { reason: 'OMR 檢查失敗: 區域 1 未填寫', index: 'ERR001' }, |
| | | { reason: 'OMR 檢查失敗: 區域 5 重複填寫', index: 'ERR005' }, |
| | | { reason: '條碼讀取失敗', index: 'BAR002' } |
| | | ]; |
| | | |
| | | const showPanel6 = ref<boolean>(true); // Splitter visibility for related images |
| | | const showNoteBtn = ref<boolean>(false); |
| | | const showRejectBtn = ref<boolean>(false); |
| | | |
| | | const Ingnore = ref<boolean>(false); |
| | | const NowIndex = ref<string>(''); |
| | | |
| | | const iniPath = ref<string>(''); // Should be injected or configured |
| | | const MyHotkeyid1 = ref<number>(0); |
| | | |
| | | // Point structures |
| | | const UpLPoint = ref<TPoint>({ X: 0, Y: 0 }); |
| | | const UpRPoint = ref<TPoint>({ X: 0, Y: 0 }); |
| | | const DownLPoint = ref<TPoint>({ X: 0, Y: 0 }); |
| | | const DownRPoint = ref<TPoint>({ X: 0, Y: 0 }); |
| | | |
| | | const UpLPoint_Rela = ref<TPoint>({ X: 0, Y: 0 }); |
| | | const UpRPoint_Rela = ref<TPoint>({ X: 0, Y: 0 }); |
| | | const DownLPoint_Rela = ref<TPoint>({ X: 0, Y: 0 }); |
| | | const DownRPoint_Rela = ref<TPoint>({ X: 0, Y: 0 }); |
| | | |
| | | // Hotkey simulation mapped from WMHotKey |
| | | const WMHotKey = (e: KeyboardEvent) => { |
| | | if (e.ctrlKey && e.key.toLowerCase() === 'd' && isDeleteEnabled.value) { |
| | | e.preventDefault(); |
| | | DeleteBtClick(); |
| | | if (errorItems.value.length > 0) { |
| | | selectedIndex.value = 0; |
| | | loadErrorDetails(errorItems.value[0].index); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | window.addEventListener('keydown', WMHotKey); |
| | | InitialData(); |
| | | }); |
| | | const loadErrorDetails = (id: string) => { |
| | | console.log('Loading error details for:', id); |
| | | // Mock loading from INI |
| | | primaryImage.value = 'assets/CB_IMGPSScanImp.png'; // Mock URL |
| | | relatedImage.value = 'assets/DocList.png'; // Mock URL |
| | | |
| | | onUnmounted(() => { |
| | | window.removeEventListener('keydown', WMHotKey); |
| | | }); |
| | | siteCount.value = 3; |
| | | relaSiteCount.value = 2; |
| | | siteIdx.value = 1; |
| | | relaSiteIdx.value = 1; |
| | | |
| | | const selectItem = (index: number) => { |
| | | selectedItemIndex.value = index; |
| | | ErrListLVClick(); |
| | | isDeleteEnabled.value = true; |
| | | isImmediateEnabled.value = errorItems.value.length === 0; |
| | | }; |
| | | |
| | | // Delphi Methods |
| | | const InitialData = () => { |
| | | isSitePreEnabled.value = false; |
| | | isSiteNextEnabled.value = false; |
| | | isRelaPreEnabled.value = false; |
| | | isRelaNextEnabled.value = false; |
| | | |
| | | SiteList.value = []; |
| | | RelaSiteList.value = []; |
| | | |
| | | siteIndex.value = 1; |
| | | siteTotal.value = 0; |
| | | relaSiteIndex.value = 1; |
| | | relaSiteTotal.value = 0; |
| | | |
| | | isDeleteEnabled.value = false; |
| | | }; |
| | | |
| | | const GetOMRErrini = (Index: string) => { |
| | | console.log(`Getting OMR Err INI for index: ${Index}`); |
| | | |
| | | // Mock data population based on index |
| | | SiteList.value = ['Site1', 'Site2']; |
| | | RelaSiteList.value = ['Rela1']; |
| | | Ingnore.value = true; |
| | | |
| | | siteTotal.value = SiteList.value.length; |
| | | relaSiteTotal.value = RelaSiteList.value.length; |
| | | |
| | | if (RelaSiteList.value.length > 0) { |
| | | showPanel6.value = true; |
| | | } else { |
| | | showPanel6.value = false; |
| | | } |
| | | |
| | | if (SiteList.value.length > 1) isSiteNextEnabled.value = true; |
| | | if (RelaSiteList.value.length > 1) isRelaNextEnabled.value = true; |
| | | |
| | | isDeleteEnabled.value = Ingnore.value; |
| | | |
| | | // Mock showing first errors |
| | | if (SiteList.value.length > 0) ShowOMRErr(siteIndex.value); |
| | | if (RelaSiteList.value.length > 0) ShowRelaOMRErr(relaSiteIndex.value); |
| | | }; |
| | | |
| | | const ErrListLVClick = () => { |
| | | InitialData(); |
| | | if (selectedItemIndex.value === -1 || !errListItems.value[selectedItemIndex.value]) return; |
| | | |
| | | NowIndex.value = errListItems.value[selectedItemIndex.value].index; |
| | | GetOMRErrini(NowIndex.value); |
| | | }; |
| | | |
| | | const ErrListLVKeyUp = (e: KeyboardEvent) => { |
| | | if (e.key === 'ArrowUp' || e.key === 'ArrowDown') { |
| | | ErrListLVClick(); |
| | | } |
| | | }; |
| | | |
| | | const ErrListLVMouseDown = (e: MouseEvent) => { |
| | | // Right click |
| | | if (e.button === 2) { |
| | | ErrListLVClick(); |
| | | } |
| | | const ErrListLVClick = (index: number) => { |
| | | selectedIndex.value = index; |
| | | loadErrorDetails(errorItems.value[index].index); |
| | | }; |
| | | |
| | | const DeleteBtClick = () => { |
| | | InitialData(); |
| | | if (Ingnore.value) { |
| | | console.log(`Writing Del=True to INI for ${NowIndex.value}`); |
| | | if (selectedIndex.value === -1) return; |
| | | |
| | | const idx = selectedItemIndex.value; |
| | | if (idx !== -1) { |
| | | errListItems.value.splice(idx, 1); |
| | | |
| | | if (errListItems.value.length === 0) { |
| | | console.log('All errors deleted, enabling Immediate button and writing OMRCheckOk.dat'); |
| | | errorItems.value.splice(selectedIndex.value, 1); |
| | | if (errorItems.value.length === 0) { |
| | | isImmediateEnabled.value = true; |
| | | selectedIndex.value = -1; |
| | | } else { |
| | | selectedItemIndex.value = Math.min(idx, errListItems.value.length - 1); |
| | | ErrListLVClick(); |
| | | if (selectedIndex.value >= errorItems.value.length) { |
| | | selectedIndex.value = errorItems.value.length - 1; |
| | | } |
| | | } |
| | | } else { |
| | | alert('此項目不可刪除或已無可刪除項目'); |
| | | loadErrorDetails(errorItems.value[selectedIndex.value].index); |
| | | } |
| | | }; |
| | | |
| | | const EnforceBtClick = () => { |
| | | InitialData(); |
| | | let deletedAny = false; |
| | | |
| | | for (let i = errListItems.value.length - 1; i >= 0; i--) { |
| | | const itemIgnorable = true; |
| | | |
| | | if (itemIgnorable) { |
| | | console.log(`Writing Del=True for ${errListItems.value[i].index}`); |
| | | errListItems.value.splice(i, 1); |
| | | deletedAny = true; |
| | | } |
| | | } |
| | | |
| | | if (errListItems.value.length === 0 && deletedAny) { |
| | | console.log('All errors enforced, enabling Immediate button and writing OMRCheckOk.dat'); |
| | | if (confirm('是否確定強制送件?')) { |
| | | errorItems.value = []; |
| | | isImmediateEnabled.value = true; |
| | | selectedIndex.value = -1; |
| | | } |
| | | }; |
| | | |
| | | const ImmediateBtClick = () => { |
| | | console.log('ImmediateBtClick: ' + logTimeString() + ' 立即傳送'); |
| | | console.log('Immediate send triggered'); |
| | | closeForm('ok'); |
| | | }; |
| | | |
| | |
| | | closeForm('cancel'); |
| | | }; |
| | | |
| | | const NoteBtClick = () => { |
| | | console.log('Ch_WriteNote = True'); |
| | | closeForm('note'); |
| | | }; |
| | | |
| | | const RejectBtClick = () => { |
| | | if (confirm('是否確定退件??')) { |
| | | console.log('RejectCase = True'); |
| | | closeForm('reject'); |
| | | } |
| | | }; |
| | | |
| | | const Button1Click = () => { |
| | | alert(`UpLPoint=${UpLPoint.value.X},${UpLPoint.value.Y}\n` + |
| | | `UpRPoint=${UpRPoint.value.X},${UpRPoint.value.Y}\n` + |
| | | `DownLPoint=${DownLPoint.value.X},${DownLPoint.value.Y}\n` + |
| | | `DownRPoint=${DownRPoint.value.X},${DownRPoint.value.Y}`); |
| | | const SitePreBtClick = () => { |
| | | if (siteIdx.value > 1) siteIdx.value--; |
| | | }; |
| | | |
| | | const SiteNextBtClick = () => { |
| | | siteIndex.value++; |
| | | ShowOMRErr(siteIndex.value); |
| | | |
| | | isSitePreEnabled.value = false; |
| | | isSiteNextEnabled.value = false; |
| | | if (siteIndex.value > 1) isSitePreEnabled.value = true; |
| | | if (siteIndex.value < siteTotal.value) isSiteNextEnabled.value = true; |
| | | }; |
| | | |
| | | const SitePreBtClick = () => { |
| | | siteIndex.value--; |
| | | ShowOMRErr(siteIndex.value); |
| | | |
| | | isSitePreEnabled.value = false; |
| | | isSiteNextEnabled.value = false; |
| | | if (siteIndex.value > 1) isSitePreEnabled.value = true; |
| | | if (siteIndex.value < siteTotal.value) isSiteNextEnabled.value = true; |
| | | }; |
| | | |
| | | const RelaNextBtClick = () => { |
| | | relaSiteIndex.value++; |
| | | ShowRelaOMRErr(relaSiteIndex.value); |
| | | |
| | | isRelaPreEnabled.value = false; |
| | | isRelaNextEnabled.value = false; |
| | | if (relaSiteIndex.value > 1) isRelaPreEnabled.value = true; |
| | | if (relaSiteIndex.value < relaSiteTotal.value) isRelaNextEnabled.value = true; |
| | | if (siteIdx.value < siteCount.value) siteIdx.value++; |
| | | }; |
| | | |
| | | const RelaPreBtClick = () => { |
| | | relaSiteIndex.value--; |
| | | ShowRelaOMRErr(relaSiteIndex.value); |
| | | |
| | | isRelaPreEnabled.value = false; |
| | | isRelaNextEnabled.value = false; |
| | | if (relaSiteIndex.value > 1) isRelaPreEnabled.value = true; |
| | | if (relaSiteIndex.value < relaSiteTotal.value) isRelaNextEnabled.value = true; |
| | | if (relaSiteIdx.value > 1) relaSiteIdx.value--; |
| | | }; |
| | | |
| | | const ShowOMRErr = (Idx: number) => { |
| | | if (Idx > SiteList.value.length) return; |
| | | console.log(`Showing OMR Error shape for index ${Idx}`); |
| | | }; |
| | | |
| | | const ShowRelaOMRErr = (RelaIdx: number) => { |
| | | if (RelaIdx > RelaSiteList.value.length) return; |
| | | console.log(`Showing Related OMR Error shape for index ${RelaIdx}`); |
| | | }; |
| | | |
| | | // Missing or external methods mapped |
| | | const logTimeString = (): string => { |
| | | const now = new Date(); |
| | | const pad = (n: number) => (n < 10 ? '0' + n : n); |
| | | return `${now.getFullYear()}${pad(now.getMonth()+1)}${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())} `; |
| | | const RelaNextBtClick = () => { |
| | | if (relaSiteIdx.value < relaSiteCount.value) relaSiteIdx.value++; |
| | | }; |
| | | |
| | | const closeForm = (result: string) => { |
| | | console.log(`Form closing with result: ${result}`); |
| | | console.log(`ErrlistForm closing with result: ${result}`); |
| | | }; |
| | | |
| | | const startResize = (e: MouseEvent) => { |
| | | console.log('Splitter moving started'); |
| | | }; |
| | | onMounted(() => { |
| | | FormCreate(); |
| | | }); |
| | | |
| | | return { |
| | | errListItems, |
| | | selectedItemIndex, |
| | | // State |
| | | errorItems, |
| | | selectedIndex, |
| | | primaryImage, |
| | | relatedImage, |
| | | siteIdx, |
| | | siteCount, |
| | | relaSiteIdx, |
| | | relaSiteCount, |
| | | isDeleteEnabled, |
| | | isImmediateEnabled, |
| | | |
| | | siteIndex, |
| | | siteTotal, |
| | | isSitePreEnabled, |
| | | isSiteNextEnabled, |
| | | |
| | | relaSiteIndex, |
| | | relaSiteTotal, |
| | | isRelaPreEnabled, |
| | | isRelaNextEnabled, |
| | | |
| | | showPanel6, |
| | | showNoteBtn, |
| | | showRejectBtn, |
| | | |
| | | selectItem, |
| | | // Actions |
| | | ErrListLVClick, |
| | | ErrListLVKeyUp, |
| | | ErrListLVMouseDown, |
| | | DeleteBtClick, |
| | | EnforceBtClick, |
| | | ImmediateBtClick, |
| | |
| | | SitePreBtClick, |
| | | SiteNextBtClick, |
| | | RelaPreBtClick, |
| | | RelaNextBtClick, |
| | | NoteBtClick, |
| | | RejectBtClick, |
| | | Button1Click, |
| | | startResize |
| | | RelaNextBtClick |
| | | }; |
| | | } |