🌐Vue 3 實戰:把「APS資料彙整」改成單一圖片頁(MC流程圖),並修好字型不一致與按鈕掉行問題

 

摘要(TL;DR)

把原本含 API/表格/Pinia 的 PageFive.vue 改為只顯示一張 MC 流程圖的簡單頁面,標題統一使用與其他頁相同的 .title-bar 樣式,用 flex 佈局讓「標題在左、按鈕在右」永遠同一行,並提供兩種字型一致的做法(全域或單頁)。同時加上「原尺寸查看」與「下載圖片」按鈕。


背景與需求

  • 既有頁面:PageFive.vue(原「APS資料彙整」)

    • 具備下拉查詢、API、Pinia 狀態、表格與水平捲動條。

  • 新需求:

    1. 改為只放入一張圖片(MC 流程圖)。

    2. 標題改為 「MC流程圖」

    3. 與其他頁一致的標題樣式與字型。

    4. 標題列右邊有「原尺寸查看/下載圖片」按鈕,不能掉到下一行


問題點

  1. 字型不一致:此頁沒有吃到全域字型設定,或被 scoped 隔離導致樣式未繼承。

  2. 按鈕掉到下一行:使用 float 或標題 h3 預設外距導致計算差異,遇到不同寬度時容易斷行。

  3. 中文檔名的風險:建置/CI/CD 偶爾會因中文檔名產生路徑問題。


改造目標

  • 刪除 API / Pinia / 表格 / 捲動條,改為單圖展示

  • .title-bar 與其他頁完全一致(你提供的 CSS)。

  • Flexbox 讓標題與按鈕同列、左右分佈

  • 兩顆按鈕:原尺寸查看下載圖片

  • 字型統一(兩種方案:全域或單頁)。


完整範例:精簡後的 PageFive.vue

圖片請放在 src/assets/MC流程圖.png(若你的專案習慣不同,調整 import 路徑即可)。
若擔心中文檔名,建議改名為 mc-flow.png 並同步修改路徑。

<!-- 檔案名稱 : PageFive.vue 功能說明 : 「MC流程圖」頁面(單一圖片展示) 主要特性 : - 只顯示 1 張流程圖,隨視窗自適應寬度 - 標題列樣式與其他頁一致;使用 flex 保持按鈕不換行 - 提供「原尺寸查看」與「下載圖片」操作 使用說明 : 1) 圖片置於 src/assets/MC流程圖.png(或調整 import 路徑) 2) 無任何 API / Pinia 依賴 注意事項 : - 若 CI/CD 對中文檔名敏感,建議改名 mc-flow.png 作者 : Windy Huang --> <script setup lang="js"> import mcFlowUrl from '@/assets/MC流程圖.png' const openOriginal = () => window.open(mcFlowUrl, '_blank') </script> <template> <div class="container"> <!-- 標題列(樣式與其他頁一致;內層以 flex 排版) --> <div class="title-bar"> <div class="title-inner"> <h3 class="title-text">MC流程圖</h3> <div class="title-actions"> <button class="button outline" @click="openOriginal">原尺寸查看</button> <a class="button blue" :href="mcFlowUrl" download="MC流程圖.png">下載圖片</a> </div> </div> </div> <!-- 圖片展示 --> <div class="image-wrap"> <figure class="image-card"> <img :src="mcFlowUrl" alt="MC流程圖" /> <figcaption>MC流程圖</figcaption> </figure> </div> </div> </template> <style scoped> /* 版面容器 */ .container { width: 100%; position: absolute; top: 75px; /* 避免被頂部固定 header 擋住 */ left: 0; background-color: #fff; min-height: calc(100vh - 75px); } /* ★ 與其他頁一致的標題列樣式(你提供的 CSS) */ .title-bar { width: 100%; background: linear-gradient(to bottom, #559fe8, #0056b3); color: white; padding: 15px 20px; font-size: 18px; font-weight: bold; text-align: left; box-sizing: border-box; } /* 內層 flex:標題靠左、按鈕靠右,同列不換行 */ .title-inner { display: flex; align-items: center; justify-content: space-between; gap: 12px; } .title-text { margin: 0; /* 移除 h3 預設外距,避免擠壓 */ font: inherit; /* 與 .title-bar 字重/字級一致 */ line-height: 1.1; } .title-actions { display: flex; gap: 10px; flex-shrink: 0; /* 避免被擠壓換行 */ white-space: nowrap; /* 兩顆鈕維持同列 */ } /* 按鈕(承接標題列字級/字型) */ .button { display: inline-flex; align-items: center; justify-content: center; padding: 6px 12px; height: 32px; border-radius: 6px; text-decoration: none; cursor: pointer; font: inherit; } .button.blue { background-color: #0056b3; color: #fff; border: none; } .button.outline{ background: transparent; color: #fff; border: 1px solid rgba(255,255,255,.85); } /* 圖片展示卡片 */ .image-wrap { width: 100%; padding: 20px; box-sizing: border-box; display: grid; place-items: center; } .image-card { max-width: 1600px; width: 100%; background: #fff; border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); padding: 12px; box-sizing: border-box; } .image-card img { width: 100%; height: auto; display: block; border-radius: 8px; } .image-card figcaption { text-align: center; color: #555; font-size: 13px; margin-top: 8px; } /* 窄螢幕容錯(可選) */ @media (max-width: 640px) { .title-inner { flex-wrap: wrap; } .title-actions { margin-top: 8px; } } </style>

字型一致的兩種作法

A. 全域統一(建議)

src/assets/styles/base.css(或你的全域樣式)中加入:

:root { --app-font: "Noto Sans TC", "Microsoft JhengHei", "PingFang TC", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; } html, body, #app { font-family: var(--app-font); font-size: 14px; color: #222; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }

並在 main.ts/main.js 匯入一次:

import "@/assets/styles/base.css"

B. 單頁補齊(暫時)

PageFive.vue<style scoped> 補:

:global(:root){ --app-font:"Noto Sans TC","Microsoft JhengHei","PingFang TC", system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif; } .container, .title-bar, .button, .image-card figcaption, .title-text { font-family: var(--app-font); color:#222; }

為什麼改用 Flex 就不會掉行?

  • float 需要額外清除(clearfix),且在不同瀏覽器字距/外距計算下容易產生高度撐大寬度不足的狀況,導致按鈕被擠下去。

  • display:flexjustify-content:space-between + white-space:nowrap 能穩定把左標題右按鈕固定在同一列。

  • flex-shrink:0 確保按鈕區不會被壓縮到換行。


圖片與可用性的小建議

  • 檔名:若 CI/CD 對中文檔名敏感,改為 mc-flow.png

  • Alt 文字alt="MC流程圖" 有助於 SEO 與無障礙。

  • 寬度自適應img{width:100%;height:auto;} 保持比例,避免變形。

  • 原尺寸查看/下載:提供實際檔案存取,方便內部文件傳閱或列印。


驗收清單(Checklist)

  • 頁面只顯示一張 MC 流程圖

  • 標題顯示 MC流程圖,樣式與其他頁一致

  • 標題右側有兩顆按鈕,桌面與常見筆電解析度不會掉行

  • 字型與其他頁一致(全域或單頁其一)

  • 手機寬度仍可正常閱讀(可選的 media query)

  • 圖片 alt 文字正確

  • 圖片路徑於各環境(dev/test/prod)皆可載入


常見踩雷

  • Scoped 限制<style scoped> 可能擋到全域字型,記得用 :global 或移到全域 CSS。

  • h3 預設外距:標題元素的 margin 容易把列高撐大,記得歸零。

  • 以為 float 萬能:布局請改用 flex/grid,維護性與穩定性更高。

  • 圖片太大:必要時可壓縮、或提供 webp 版本加速載入。


結語

這次改造的關鍵,在於解耦頁面職責(單圖展示)、統一設計系統(標題與字型一致),以及用 Flex 解決排版穩定性。程式更簡潔,使用者也得到一致的體驗。把這套做法推廣到其他單純展示頁,能明顯降低維護成本。

留言

這個網誌中的熱門文章

🛠【ASP.NET Core + Oracle】解決 ORA-00904 "FALSE": 無效的 ID 錯誤與資料欄位動態插入顯示問題

🛠【實戰排除教學】從 VS Code 的 _logger 錯誤,到 PowerShell 找不到 npm/serve,再到 Oracle ORA-03135 連線中斷——一次搞懂!

🔎如何在 Oracle PL/SQL 儲存過程中為文字欄位加入換行符號(CHR(10))——以 Updlcmremark 為例