diff --git a/src/components/OrganizationTreeDiagram.vue b/src/components/OrganizationTreeDiagram.vue index 60f56e1..a6926f4 100644 --- a/src/components/OrganizationTreeDiagram.vue +++ b/src/components/OrganizationTreeDiagram.vue @@ -108,12 +108,10 @@ const setupD3Tree = (preserveState = false) => { rootNode = d3.hierarchy(dataToHierarchy, d => d.children); - // --- เพิ่ม LOG ตรงนี้ --- console.log("D3 Hierarchy - Root Node children:", rootNode.children ? rootNode.children.map(c => c.id) : "No children (single root)"); rootNode.descendants().forEach(d => { console.log(`D3 Hierarchy - Node: ${d.id}, Depth: ${d.depth}, isDashed: ${d.data.isDashed}, reportsTo: ${d.data.reportsTo}`); }); - // ---------------------- treemap(rootNode); // Compute initial layout for all nodes @@ -171,19 +169,14 @@ const update = (source) => { const isArrayRoot = Array.isArray(props.treeData); - // Filter visible nodes based on current children/depth - // A node is visible if it's the root, or if its parent is visible and it's in the parent's 'children' array const visibleNodes = allNodesInLayout.filter(d => { - // The dummy_root is always "visible" in terms of layout calculation, - // but not rendered as a node. + if (d.id === 'dummy_root') return true; - // For any other node, it's visible if it's a direct child of an expanded node - // or if it's the actual root (depth 0 for object root, depth 1 for array root). + const isActualRoot = (!isArrayRoot && d.depth === 0) || (isArrayRoot && d.depth === 1 && d.parent.id === 'dummy_root'); - // If it's a root or if its parent is expanded (has children, not _children) - // AND it's one of the current direct children of its parent + return isActualRoot || (d.parent && d.parent.children && d.parent.children.includes(d)); }); @@ -197,18 +190,13 @@ const update = (source) => { // Find the actual main root node (e.g., alpha_root) among all nodes in layout const mainRoot = allNodesInLayout.find(d => d.id === 'alpha_root'); - // 1. Generate standard D3 links (parent-child relationships) for visible nodes - // Ensure source and target are both visible for the link to be considered. treemap(rootNode).links().forEach(link => { - // If using dummy_root, only draw links *from* dummy_root if they lead to an actual root node, - // AND that actual root node is NOT a dashed one. + if (isArrayRoot && link.source.id === 'dummy_root') { - // Check if target node's data exists and is not marked as dashed itself if (link.target.data && !link.target.data.isDashed && nodesToRender.some(n => n.id === link.target.id)) { links.push(link); } } else { - // For normal parent-child links, both source and target must be visible nodes to render const sourceVisible = nodesToRender.some(n => n.id === link.source.id); const targetVisible = nodesToRender.some(n => n.id === link.target.id); if (sourceVisible && targetVisible) { @@ -217,7 +205,6 @@ const update = (source) => { } }); - // 2. Add custom dashed links (e.g., independent units reporting to mainRoot) if (mainRoot) { // Only add dashed links if mainRoot exists allNodesInLayout.forEach(node => { if (node.data.isDashed && node.data.reportsTo === mainRoot.id) { @@ -225,13 +212,11 @@ const update = (source) => { const isSourceVisible = nodesToRender.some(n => n.id === mainRoot.id); // mainRoot should always be visible if it's the core. if (isNodeVisible && isSourceVisible) { - // Create a new link object for the dashed line - // Ensure it uses the actual D3 node objects for source and target - // Add a 'data' property directly to this link object to mark it as dashed + links.push({ - source: mainRoot, // The D3 node object for alpha_root - target: node, // The D3 node object for the dashed node - data: { // This 'data' property is specific to this link object + source: mainRoot, + target: node, + data: { isDashed: true } }); @@ -243,7 +228,6 @@ const update = (source) => { console.log("Final links (including custom):", links.map(d => { const sourceId = d.source ? d.source.id : 'N/A'; const targetId = d.target ? d.target.id : 'N/A'; - // Check for dashed status on the link object first, then target node const isDashed = (d.data && d.data.isDashed) || (d.target && d.target.data && d.target.data.isDashed); return `${sourceId} -> ${targetId} (Dashed: ${isDashed})`; })); diff --git a/src/stores/app.js b/src/stores/app.js index 70770cf..903a1d4 100644 --- a/src/stores/app.js +++ b/src/stores/app.js @@ -13,8 +13,7 @@ export const useAppStore = defineStore('app', { { title: "Press Release", title_en: "Press Release", category: "GeneralPublic" }, { title: "ข่าวบริการประชาชน", title_en: "Public Service News", category: "EventActivities" }, ], - // *** ข้อมูลสำหรับ Header *** - // *** ข้อมูลสำหรับ Header ที่ปรับปรุงแล้ว *** + headers: { header_background: { url: '/images/news_header_bg_b815923058.png' }, logo: { url: '/images/Enter.png' }, // ใช้รูปโลโก้ตามที่ระบุ @@ -174,8 +173,7 @@ export const useAppStore = defineStore('app', { { id: 58, title_th: 'ถาม ตอบ', title_en: 'Q&A / FAQ', link: '/contact/faq-new', order: 8, active: true, active_en: true }, ] }, - // คุณสามารถเพิ่มกลุ่ม "ร้องทุกข์ร้องเรียน" แยกออกมาได้หากต้องการให้เป็นคอลัมน์ของตัวเอง - // หรือจะรวมไว้ในกลุ่ม "บริการช่วยเหลือ" ก็ได้ + // { // group_title_th: 'ร้องทุกข์', // group_title_en: 'Complaints', diff --git a/src/stores/infoDisseminationStore.js b/src/stores/infoDisseminationStore.js index 8fc649e..a6d972b 100644 --- a/src/stores/infoDisseminationStore.js +++ b/src/stores/infoDisseminationStore.js @@ -97,7 +97,7 @@ export const useInfoDisseminationStore = defineStore('infoDissemination', { embedUrl: state.getYoutubeEmbedUrl(v.rawUrl), // ตรงนี้คือที่สร้าง embedUrl thumb: state.getYoutubeThumbnail(v.rawUrl), })); - // **เพิ่ม console.log นี้:** + console.log('getVideosForDisplay output (ตรวจสอบ embedUrl):', videos); return videos; }, @@ -109,7 +109,7 @@ export const useInfoDisseminationStore = defineStore('infoDissemination', { return sourceGalleries; }, getAudioForDisplay: (state) => { - // **แก้ไข: ลบ () ออก** เพราะ getMockAudioData เป็น getter ที่คืนค่า Array โดยตรง + const sourceAudio = state.audio.length > 0 ? state.audio : state.getMockAudioData; console.log('getAudioForDisplay output:', sourceAudio); return sourceAudio; @@ -161,8 +161,8 @@ export const useInfoDisseminationStore = defineStore('infoDissemination', { }, getFilteredDocuments: (state) => { - const appStore = useAppStore(); // <--- Import และเรียกใช้ appStore ภายใน getter - // **แก้ไข: ลบ () ออก** + const appStore = useAppStore(); + const allDocs = state.allRawDocuments.length > 0 ? state.allRawDocuments : state.getMockDocumentsData; if (appStore.isTh) { // <--- ใช้ appStore.isTh return allDocs.filter(doc => doc.active); @@ -172,8 +172,8 @@ export const useInfoDisseminationStore = defineStore('infoDissemination', { }, getFilteredPublications: (state) => { - const appStore = useAppStore(); // <--- Import และเรียกใช้ appStore ภายใน getter - // **แก้ไข: ลบ () ออก** + const appStore = useAppStore(); + let filteredData = state.allRawPublications.length > 0 ? state.allRawPublications : state.getMockPublicationsData; if (appStore.isTh) { // <--- ใช้ appStore.isTh filteredData = filteredData.filter(pub => pub.Active); @@ -184,9 +184,6 @@ export const useInfoDisseminationStore = defineStore('infoDissemination', { return filteredData; }, - // Getter เหล่านี้ไม่จำเป็นต้องใช้โดยตรงใน JournalView.vue แล้ว - // เพราะเราจะใช้ allPublications แล้วกรองด้วย computed property ใน JournalView.vue แทน - // แต่ถ้ามี component อื่นที่ยังใช้ สามารถเก็บไว้ได้ getMagazinePublications: (state) => { return state.getFilteredPublications.filter(pub => pub.type === 'magazine'); }, @@ -223,18 +220,14 @@ export const useInfoDisseminationStore = defineStore('infoDissemination', { actions: { async fetchDocuments() { - // **แก้ไข: ลบ () ออก** this.allRawDocuments = this.getMockDocumentsData; }, async fetchPublications() { - // ดึงข้อมูล Publications ดิบจาก Mock - // **แก้ไข: ลบ () ออก** + const rawPublications = this.getMockPublicationsData; this.allRawPublications = rawPublications; - // กรองข้อมูลตามประเภท (คล้ายกับ logic ใน getters แต่ทำใน action เพื่อคืนค่า) - // Note: Journal (ตัว J ใหญ่) เป็นค่า type ที่ถูกต้องตาม mock data const journal = rawPublications.filter(pub => pub.type === 'Journal'); const dailynews = rawPublications.filter(pub => pub.type === 'dailynews'); const magazine = rawPublications.filter(pub => pub.type === 'magazine'); @@ -319,7 +312,7 @@ export const useInfoDisseminationStore = defineStore('infoDissemination', { this.isLoading.audio = false; } }, - // เพิ่มฟังก์ชันนี้กลับเข้าไป + async simulateDelay() { return new Promise(resolve => setTimeout(resolve, 500)); }, diff --git a/src/views/info-dissemination/PublicationsView.vue b/src/views/info-dissemination/PublicationsView.vue index aa1762f..0ec5868 100644 --- a/src/views/info-dissemination/PublicationsView.vue +++ b/src/views/info-dissemination/PublicationsView.vue @@ -124,7 +124,7 @@ import { useInfoDisseminationStore } from '@/stores/infoDisseminationStore'; import { useAppStore } from '@/stores/app'; // Import Flipbook component -import Flipbook from 'flipbook-vue'; // หรือ import Flipbook จาก path ที่ถูกต้องของคุณ เช่น '@/components/Flipbook.vue'; +import Flipbook from 'flipbook-vue'; // Constants const INITIAL_ITEMS = 8; @@ -141,8 +141,8 @@ const itemsToShow = ref(INITIAL_ITEMS); const searchTerm = ref(''); const overlay = ref(false); -const currentFlipbookPages = ref([]); // เปลี่ยนชื่อจาก 'pages' เป็น 'currentFlipbookPages' -const flipbookComponent = ref(null); // เปลี่ยนชื่อจาก 'flip' เป็น 'flipbookComponent' +const currentFlipbookPages = ref([]); +const flipbookComponent = ref(null); const isFlipping = ref(false); // Computed Properties