[{"data":1,"prerenderedAt":71},["ShallowReactive",2],{"project:accuhit-campaign-hub:zh-tw":3,"i-tabler:route":59,"i-tabler:database":63,"i-tabler:shield-check":65,"i-tabler:components":67,"i-tabler:login":69},{"slug":4,"name":5,"summary":6,"role":7,"updateNote":-1,"meta":8,"coverUrl":-1,"lang":23,"isFallback":24,"featuredRank":25,"badge":26,"lastActivity":18,"tapeNumber":27,"blocks":28},"accuhit-campaign-hub","活動頁整合平台","把分散在各活動頁、以傳統 HTML 與 JS 撰寫的多個客戶端專案，整合成以 Vue 與 Vuetify 打造的單一應用。","前端工程師",{"origin":9,"categories":10,"tags":12,"released":18,"company":19,"period":20},"company",[11],"frontend",[13,14,15,16,17],"vue","typescript","vuetify","pinia","liff","2025-11-01","accuhit",{"from":21,"to":22},"2025-11","2026-01","zh-TW",false,3,null,5,[29,52],{"type":30,"items":31},"features",[32,36,40,44,48],{"title":33,"description":34,"icon":35},"多專案路徑整合","將多個活動頁整合到同一個應用，以路徑區分。導流時只需處理各路徑所需的資料，例如網址帶入的參數。","tabler:route",{"title":37,"description":38,"icon":39},"設定的單一來源（SSOT）","把各專案不同的 UI 與設定彙整成單一來源，型別由設定本身推導，降低撰寫錯誤與維護成本。","tabler:database",{"title":41,"description":42,"icon":43},"型別約束的設定對照表","以對照表取代分散在各處的 switch 判斷。新增方案時漏寫任何設定，型別檢查就會報錯，未知的值則回退到預設。","tabler:shield-check",{"title":45,"description":46,"icon":47},"統一的 UI","以 Vuetify 統一各活動頁的介面，取代各自為政的樣式。","tabler:components",{"title":49,"description":50,"icon":51},"LINE 登入與例外處理","以 LIFF 串接 LINE 登入，統一處理載入流程與登入失效等例外情況。","tabler:login",{"type":53,"title":54,"problem":55,"solution":57},"challenge","活動頁各自為政，改一處要動好幾處",[56],"多個活動頁各自以 HTML、JS 撰寫，UI 不一致。同類設定分散在各處，規則容易分歧，改一處要連動修改好幾處。",[58],"整合成 Vue 的單一應用，以路徑區分各專案。設定集中成單一來源，並以 TypeScript 約束，漏寫或寫錯在型別檢查就會發現。",{"left":60,"top":60,"width":61,"height":61,"rotate":60,"vFlip":24,"hFlip":24,"body":62},0,24,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 19a2 2 0 1 0 4 0a2 2 0 0 0-4 0M19 7a2 2 0 1 0 0-4a2 2 0 0 0 0 4m-8 12h5.5a3.5 3.5 0 0 0 0-7h-8a3.5 3.5 0 0 1 0-7H13\"\u002F>",{"left":60,"top":60,"width":61,"height":61,"rotate":60,"vFlip":24,"hFlip":24,"body":64},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M4 6a8 3 0 1 0 16 0A8 3 0 1 0 4 6\"\u002F>\u003Cpath d=\"M4 6v6a8 3 0 0 0 16 0V6\"\u002F>\u003Cpath d=\"M4 12v6a8 3 0 0 0 16 0v-6\"\u002F>\u003C\u002Fg>",{"left":60,"top":60,"width":61,"height":61,"rotate":60,"vFlip":24,"hFlip":24,"body":66},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M11.46 20.846A12 12 0 0 1 3.5 6A12 12 0 0 0 12 3a12 12 0 0 0 8.5 3a12 12 0 0 1-.09 7.06M15 19l2 2l4-4\"\u002F>",{"left":60,"top":60,"width":61,"height":61,"rotate":60,"vFlip":24,"hFlip":24,"body":68},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m3 12l3 3l3-3l-3-3zm12 0l3 3l3-3l-3-3zM9 6l3 3l3-3l-3-3zm0 12l3 3l3-3l-3-3z\"\u002F>",{"left":60,"top":60,"width":61,"height":61,"rotate":60,"vFlip":24,"hFlip":24,"body":70},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M15 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2v-2\"\u002F>\u003Cpath d=\"M21 12H8l3-3m0 6l-3-3\"\u002F>\u003C\u002Fg>",1793955809408]