yuwen
2025-11-12 628ee4a8325f47848116f20afe30697d243db9dc
feat: integrate Tailwind CSS and improve class merging utility
修改4個檔案
新增4個檔案
7401 ■■■■■ 已變更過的檔案
.prettierrc.json 7 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
package-lock.json 7355 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
package.json 6 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
src/assets/css/main.css 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
src/assets/css/tailwind.css 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
src/main.ts 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
src/utils/cn.ts 21 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
vite.config.ts 9 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
.prettierrc.json
@@ -2,5 +2,8 @@
  "$schema": "https://json.schemastore.org/prettierrc",
  "semi": false,
  "singleQuote": true,
  "printWidth": 100
}
  "printWidth": 100,
  "plugins": [
    "prettier-plugin-tailwindcss"
  ]
}
package-lock.json
比對新檔案
檔案太大
package.json
@@ -18,7 +18,10 @@
    "format": "prettier --write src/"
  },
  "dependencies": {
    "@tailwindcss/vite": "^4.1.16",
    "pinia": "^3.0.3",
    "tailwind-merge": "^3.4.0",
    "tailwindcss": "^4.1.16",
    "vue": "^3.5.22",
    "vue-router": "^4.6.3"
  },
@@ -40,7 +43,8 @@
    "jiti": "^2.6.1",
    "jsdom": "^27.0.1",
    "npm-run-all2": "^8.0.4",
    "prettier": "3.6.2",
    "prettier": "^3.6.2",
    "prettier-plugin-tailwindcss": "^0.7.1",
    "typescript": "~5.9.0",
    "vite": "^7.1.11",
    "vite-plugin-vue-devtools": "^8.0.3",
src/assets/css/main.css
比對新檔案
@@ -0,0 +1 @@
@import './tailwind.css';
src/assets/css/tailwind.css
比對新檔案
@@ -0,0 +1 @@
@import 'tailwindcss';
src/main.ts
@@ -3,6 +3,7 @@
import App from './App.vue'
import router from './router'
import '@/assets/css/main.css'
const app = createApp(App)
src/utils/cn.ts
比對新檔案
@@ -0,0 +1,21 @@
import { twMerge } from 'tailwind-merge'
import { normalizeClass } from 'vue'
/** 解決 tailwind-css 引發的樣式衝突,此函式會依照參數順序決定最終套用的樣式。
 *
 * @ 當元件根據不同狀態而異動一個先前已預設好之樣式時,可能會因為 CSS 優先級發生衝突,導致未能套用預期樣式
 *
 * @example
 * :class="cn('bg-white', { 'bg-black': props.bg === 'black' })"
 */
export default function cn(...inputs: Parameters<typeof normalizeClass>) {
  return twMerge(normalizeClass(inputs))
}
type ClassDictionary = Record<string, unknown>
type ClassArray = ClassValue[]
type ClassValue = ClassArray | ClassDictionary | string | number | null | boolean | undefined
declare module 'vue' {
  function normalizeClass(...inputs: ClassValue[]): string
}
vite.config.ts
@@ -1,20 +1,17 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    vueJsx(),
    vueDevTools(),
  ],
  plugins: [vue(), vueJsx(), vueDevTools(), tailwindcss()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
})