🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

【AI 編程實戰】第 4 篇:一次完美 vs 五輪對話 - UnoCSS 配置的正確姿勢

很多教程告訴你「寫好提示詞就能讓 AI 一次給出正確答案」,但現實是:你不可能一開始就知道所有細節。真正高效的 AI 協作,是在對話中逐步明確需求。這篇文章通過一個完整的 UnoCSS 配置案例,展示我和 TRAE SOLO 的真實互動過程——從模糊想法到完整方案,中間經歷了哪些溝通和調整。

這是《AI 編程實戰:TRAE SOLO 全棧開發指南》專欄的第四篇文章,帶你學會如何與 AI 正確的溝通協作。

一、開篇:別被「完美提示詞」騙了

1.1 一個常見的誤區

網上很多 AI 教程會給你看這樣的「完美提示詞」:

幫我配置 UnoCSS,項目環境和需求如下:
【項目環境】UniApp + Vue3 + Vite,目標平台微信小程序
【功能需求】支持 attributify、@apply、圖標、安全區適配
【已知問題】小程序 transform 類需要預設 CSS 變數
【輸出要求】完整的 uno.config.ts 配置文件

然後告訴你:「看,一次就能得到完美答案!」

但問題是

  • 你一開始怎麼知道需要「安全區適配」?
  • 你怎麼知道「transform 類需要預設 CSS 變數」?
  • 這些都是踩坑之後才知道的

1.2 真實的 AI 協作是什麼樣的

真實的 AI 協作是一個漸進式對話的過程:

第 1 輪:我有個模糊的需求
    ↓
AI:給出初步方案 + 執行計劃
    ↓
第 2 輪:我發現問題 / 補充細節
    ↓
AI:調整方案
    ↓
第 3 輪:遇到報錯 / 樣式不生效
    ↓
AI:排查問題 + 修復
    ↓
最終:得到完整可用的方案

接下來,我會完整展示和 TRAE SOLO 配置 UnoCSS 的真實對話過程

二、第一輪對話:從模糊需求開始

2.1 我的第一句話

剛開始,我對 UnoCSS 的了解很有限,只知道它是「原子化 CSS」。我的第一句話很簡單:

我:項目需要用 UnoCSS,幫我配置一下

2.2 TRAE SOLO 的響應:先給執行計劃

TRAE SOLO 沒有直接開始寫代碼,而是先給出了執行計劃

TRAE SOLO:好的,我來幫你配置 UnoCSS。在開始之前,我需要先了解一些信息:

📋 執行計劃:
1. 分析項目結構,確定技術棧
2. 選擇合適的 UnoCSS 預設
3. 生成配置文件
4. 配置 Vite 插件

🤔 我有幾個問題:
1. 這是什麼類型的項目?(Vue/React/UniApp)
2. 目標運行平台是什麼?(Web/小程序/App)
3. 有沒有特別想要的功能?(圖標/attributify 模式等)

請告訴我這些信息,或者我可以先分析你的項目結構來判斷。

關鍵點:TRAE SOLO 主動詢問上下文,而不是瞎猜。

2.3 我補充信息

我:UniApp + Vue3 項目,主要跑微信小程序,也要支持 H5。
    功能的話,我也不太清楚,你看著配吧,常用的都加上。

2.4 TRAE SOLO 分析項目後給出方案

TRAE SOLO:我分析了你的項目結構,發現:
- 框架:UniApp + Vue3 + Vite
- UI 庫:已安裝 wot-design-uni
- 目標:微信小程序 + H5

📋 更新執行計劃:

1. 安裝依賴
   - unocss
   - @uni-helper/unocss-preset-uni (UniApp 專用預設,必須)
   - @iconify-json/carbon (圖標庫,可選)

2. 創建 uno.config.ts,包含:
   - presetUni:小程序適配
   - presetAttributify:支持屬性化寫法
   - presetIcons:圖標支持
   - transformerDirectives:支持 @apply 指令

3. 修改 vite.config.ts,添加 UnoCSS 插件

4. 在 main.ts 中引入 uno.css

是否按這個計劃執行?或者你想調整什麼?

2.5 我確認執行

我:可以,就按這個來
TRAE SOLO:好的,開始執行...
✅ 正在安裝依賴...
✅ 創建 uno.config.ts...
✅ 修改 vite.config.ts...
✅ 修改 main.ts...
配置完成!你可以這樣使用:

<view class="flex items-center gap-4 p-4 bg-white rounded-xl">
  <text class="text-lg font-bold">Hello UnoCSS</text>
</view>

運行 pnpm dev:mp-weixin 試試效果。

三、第二輪對話:遇到問題,繼續溝通

3.1 我發現樣式不生效

運行項目後,我發現部分樣式不生效:

我:樣式大部分生效了,但是 translate-x-2 這個類沒效果,
    元素沒有移動

3.2 TRAE SOLO 排查問題

TRAE SOLO:讓我檢查一下...
我查看了生成的 CSS,發現 translate-x-2 生成的代碼是:
transform: translateX(var(--un-translate-x));

問題在於:小程序環境沒有預設 --un-translate-x 這個 CSS 變數。

在瀏覽器中,UnoCSS 會通過 :root 選擇器預設這些變數,
但小程序不支持 :root 選擇器。

🔧 修復方案:
在 uno.config.ts 中添加 preflights,手動為小程序元素預設變數。

是否需要我幫你修復?

3.3 我讓它修復

我:幫我修復吧
TRAE SOLO:好的,我來修改 uno.config.ts...
添加了以下配置:

preflights: [
  {
    layer: 'unocss-transform-fix',
    getCSS: () => `
page, view, text, image {
  --un-translate-x: 0;
  --un-translate-y: 0;
  --un-rotate: 0;
  --un-scale-x: 1;
  --un-scale-y: 1;
  /* ... 其他變數 */
}`,
  },
],
✅ 已修復,重新運行項目試試。

3.4 我驗證修復成功

我:好了,translate 生效了

四、第三輪對話:追加新需求

4.1 我想添加安全區適配

開發過程中,我發現 iPhone 底部有安全區遮擋內容:

我:iPhone 底部有個橫條會擋住內容,UnoCSS 能處理這個嗎?

4.2 TRAE SOLO 給出方案

TRAE SOLO:這是 iPhone 的安全區問題。可以通過自定義 UnoCSS 規則來解決。

📋 方案:
添加以下自定義規則:
- pb-safe:底部安全區內邊距
- pt-safe:頂部安全區內邊距(劉海屏)
- p-safe:四邊安全區內邊距

使用方式:
<view class="pb-safe">底部內容會避開安全區</view>

是否需要我添加這些規則?
我:加上吧
TRAE SOLO:好的,在 uno.config.ts 的 rules 中添加:

rules: [
  ['pb-safe', { 'padding-bottom': 'env(safe-area-inset-bottom)' }],
  ['pt-safe', { 'padding-top': 'env(safe-area-inset-top)' }],
  ['p-safe', {
    padding: 'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)',
  }],
],
✅ 已添加,現在可以使用 pb-safe 類了。

五、第四輪對話:優化開發體驗

5.1 我覺得類名太長了

我:flex items-center justify-between 每次都要寫這麼長,
    有沒有辦法簡化?

5.2 TRAE SOLO 介紹 shortcuts

TRAE SOLO:可以用 UnoCSS 的 shortcuts 功能,把常用組合定義成短類名。

比如:
- center = flex justify-center items-center
- between = flex justify-between items-center

你想定義哪些快捷方式?或者我根據你的代碼分析常用組合?
我:你分析一下吧,看哪些用得多

5.3 TRAE SOLO 分析代碼後給出建議

TRAE SOLO:我掃描了你的代碼,發現以下組合出現頻率較高:

📊 使用頻率分析:
1. flex items-center (出現 23 次)
2. flex items-center justify-between (出現 15 次)
3. flex items-center justify-center (出現 12 次)
4. flex flex-col (出現 8 次)
5. bg-white rounded-xl p-4 (出現 7 次)

🔧 建議添加的 shortcuts:

shortcuts: [
  { 'center': 'flex justify-center items-center' },
  { 'between': 'flex justify-between items-center' },
  { 'col': 'flex flex-col' },
  { 'card': 'bg-white rounded-xl p-4' },
],
是否按這個配置?或者你想調整?
我:可以,就這樣

六、第五輪對話:處理動態類名問題

6.1 我遇到動態類名不生效

我:我有個地方根據狀態切換顏色:
    <text :class="`text-${status}-500`">狀態</text>
    status 可能是 red、green、blue,但樣式不生效

6.2 TRAE SOLO 解釋原因並給方案

TRAE SOLO:這是 UnoCSS 的一個限制。

🔍 原因:
UnoCSS 在構建時靜態掃描代碼,`text-${status}-500` 這種
動態拼接的類名無法被識別,所以不會生成對應的 CSS。

🔧 解决方案有三種:

【方案一】對象語法(推薦)
<text :class="{
  'text-red-500': status === 'red',
  'text-green-500': status === 'green',
  'text-blue-500': status === 'blue',
}">狀態</text>

【方案二】safelist 預聲明
在 uno.config.ts 中添加:
safelist: ['text-red-500', 'text-green-500', 'text-blue-500']

【方案三】CSS 變數
<text class="text-[var(--status-color)]"
      :style="{ '--status-color': statusColor }">狀態</text>

你的場景用哪種方案比較合適?
我:顏色就這三種,用方案二吧,簡單
TRAE SOLO:好的,已添加到 safelist:
safelist: [
  'text-red-500',
  'text-green-500',
  'text-blue-500',
  'i-carbon-code', // 之前已有的圖標
],
✅ 現在動態類名可以正常工作了。

七、最終配置:多輪對話的成果

經過 5 輪對話,最終的 uno.config.ts 是這樣的:

// uno.config.ts
// 這個配置是通過多輪對話逐步完善的,不是一次性寫出來的

import { presetUni } from '@uni-helper/unocss-preset-uni'
import {
  defineConfig,
  presetAttributify,
  presetIcons,
  transformerDirectives,
  transformerVariantGroup,
} from 'unocss'

export default defineConfig({
  // 【第 1 輪】基礎預設
  presets: [
    presetUni({
      attributify: {
        prefixedOnly: true,
      },
    }),
    presetIcons({
      scale: 1.2,
      warn: true,
      extraProperties: {
        'display': 'inline-block',
        'vertical-align': 'middle',
      },
    }),
    presetAttributify(),
  ],

  // 【第 1 輪】轉換器
  transformers: [
    transformerDirectives(),
    transformerVariantGroup(),
  ],

  // 【第 2 輪】修復小程序 transform 不生效
  preflights: [
    {
      layer: 'unocss-transform-fix',
      getCSS: () => `
page, view, text, image {
  --un-translate-x: 0;
  --un-translate-y: 0;
  --un-translate-z: 0;
  --un-rotate: 0;
  --un-rotate-x: 0;
  --un-rotate-y: 0;
  --un-rotate-z: 0;
  --un-skew-x: 0;
  --un-skew-y: 0;
  --un-scale-x: 1;
  --un-scale-y: 1;
  --un-scale-z: 1;
}`,
    },
  ],

  // 【第 3 輪】安全區適配
  rules: [
    ['p-safe', {
      padding: 'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)',
    }],
    ['pt-safe', { 'padding-top': 'env(safe-area-inset-top)' }],
    ['pb-safe', { 'padding-bottom': 'env(safe-area-inset-bottom)' }],
  ],

  // 【第 4 輪】常用快捷方式
  shortcuts: [
    { 'center': 'flex justify-center items-center' },
    { 'between': 'flex justify-between items-center' },
    { 'col': 'flex flex-col' },
    { 'card': 'bg-white rounded-xl p-4' },
  ],

  // 【第 5 輪】動態類名預聲明
  safelist: [
    'text-red-500',
    'text-green-500',
    'text-blue-500',
    'i-carbon-code', // 之前已有的圖標
  ],

  // 【第 1 輪】主題配置
  theme: {
    colors: {
      primary: 'var(--wot-color-theme, #0957DE)',
    },
    fontSize: {
      '2xs': ['20rpx', '28rpx'],
      '3xs': ['18rpx', '26rpx'],
    },
  },
})

八、組件開發:同樣是對話式協作

8.1 開發回复卡片組件

配置完成後,我開始開發業務組件。同樣是對話式協作:

我:幫我寫一個回复卡片組件,用來展示 AI 生成的回复。
    左邊是語氣標籤(比如「高情商」),中間是回复文字,右邊是複製按鈕。
TRAE SOLO:好的,我來幫你開發這個組件。

📋 執行計劃:
1. 創建 ReplyCard.vue 組件
2. 定義 Props:tone(語氣)、text(文本)
3. 定義 Events:copy(複製)
4. 使用 UnoCSS 原子類實現樣式

🤔 幾個問題:
1. 語氣標籤的顏色是固定的還是根據內容變化?
2. 複製按鈕是圖標還是文字?
3. 有沒有設計稿可以參考?
我:標籤顏色根據語氣類型自動變,用哈希算法分配吧。
    複製按鈕用圖標。設計稿沒有,你自己設計一個好看的。
TRAE SOLO:明白了,我來實現:

【設計方案】
- 卡片:白色背景、圓角、內邊距
- 標籤:小圓角、根據文字哈希分配 5 種顏色
- 文本:深灰色、支持多行
- 按鈕:圓形點擊區域、圖標居中

開始生成代碼...

8.2 TRAE SOLO 生成的組件

<!-- components/ReplyCard.vue -->
<template>
  <view class="flex items-center gap-2.5 bg-white rounded-xl p-4 pr-2">
    <!-- 語氣標籤 -->
    <view
      v-show="!hideTag"
      class="text-xs font-bold rounded-sm px-2 py-1 flex-shrink-0"
      :style="{ backgroundColor: tagStyle.bg, color: tagStyle.text }"
    >
      {{ tone }}
    </view>

    <!-- 回复文本 -->
    <view class="text-sm text-#1F2937 flex-1">
      {{ text }}
    </view>

    <!-- 複製按鈕 -->
    <view
      class="w-9 h-9 center cursor-pointer"
      @click="$emit('copy', text)"
    >
      <image src="/static/images/home/copy.svg" mode="aspectFit" class="w-5 h-5" />
    </view>
  </view>
</template>

<script setup lang="ts">
import { computed } from 'vue';

interface Props {
  tone: string;
  text: string;
  hideTag?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  hideTag: false,
});

defineEmits<{
  copy: [text: string];
}>();

// 5 種預設顏色
const COLORS = [
  { bg: '#F3E8FF', text: '#8B5CF6' },  // 紫色
  { bg: '#E6FFFA', text: '#319795' },  // 青色
  { bg: '#FFF5E6', text: '#F56500' },  // 橙色
  { bg: '#FFE4E6', text: '#E11D48' },  // 粉色
  { bg: '#E0F2FE', text: '#0284C7' },  // 藍色
];

// 根據語氣文字哈希分配顏色
const tagStyle = computed(() => {
  let hash = 0;
  for (let i = 0; i < props.tone.length; i++) {
    hash = (hash + props.tone.charCodeAt(i)) % COLORS.length;
  }
  return COLORS[hash];
});
</script>

8.3 我提出修改意見

我:不錯,但我想加一個功能:有時候不需要顯示標籤,能不能加個 prop 控制?
TRAE SOLO:已經有了,就是 hideTag 這個 prop。

使用方式:
<ReplyCard tone="高情商" text="回复內容" :hide-tag="true" />

設置 hide-tag 為 true 就會隱藏標籤。
我:哦對,我沒注意看。那再加個需求:複製成功後給個反饋
TRAE SOLO:複製反饋建議在父組件處理,因為:
1. 卡片組件應該保持簡單,只負責 UI
2. 複製邏輯和 toast 提示是業務邏輯,放父組件更合適

父組件這樣用:

<ReplyCard
  tone="高情商"
  text="回复內容"
  @copy="handleCopy"
/>

const handleCopy = async (text: string) => {
  await copyText(text);
  toast.success('已複製');
};

你覺得這樣合理嗎?還是希望把 toast 放在組件內部?
我:你說得對,放父組件更好

九、核心經驗:與 AI 協作的正確姿勢

9.1 不要追求「一次完美」

錯誤做法 正確做法
花 30 分鐘寫一個「完美提示詞」 花 1 分鐘說出需求,讓 AI 提問
一次性想清楚所有細節 邊做邊發現問題,逐步完善
把 AI 當執行工具 把 AI 當協作夥伴,可以對話

9.2 讓 AI 先給執行計劃

每次提需求後,讓 AI 先給出執行計劃

我:[需求描述]
AI:📋 執行計劃:
    1. xxx
    2. xxx
    3. xxx

    🤔 有幾個問題:
    1. xxx?
    2. xxx?

    確認後我開始執行。

好處

  • 確保 AI 理解正確
  • 發現遺漏的需求
  • 可以在執行前調整方向

9.3 遇到問題時提供上下文

❌ 錯誤方式

我:樣式不生效

✅ 正確方式

我:translate-x-2 這個類在小程序裡不生效,但在 H5 正常。
    我看了生成的 CSS,是 transform: translateX(var(--un-translate-x))。
    是不是變數沒定義?

9.4 讓 AI 解釋它的方案

當 AI 給出方案時,追問原理:

我:為什麼要用 preflights?直接寫 CSS 不行嗎?
TRAE SOLO:preflights 是 UnoCSS 的預設樣式注入機制,和直接寫 CSS 的區別:
1. preflights 會被注入到所有生成的 CSS 之前,確保優先級正確
2. 可以通過 layer 控制加載順序
3. 統一管理,修改時只需要改配置文件

直接寫 CSS 也可以,但需要確保加載順序正確,否則可能被覆蓋。

好處:理解原理後,下次遇到類似問題可以自己判斷。

十、總結:對話式協作 > 完美提示詞

10.1 本文的核心觀點

  1. 不要追求「一次完美的提示詞」,真實的 AI 協作是多輪對話
  2. 讓 AI 先給執行計劃,確認後再執行
  3. 遇到問題時提供上下文,幫助 AI 定位問題
  4. 追問原理,理解 AI 的方案,下次才能舉一反三

10.2 5 輪對話完成的工作

輪次 需求 成果
第 1 輪 基礎配置 presets、transformers、theme
第 2 輪 修復 transform 問題 preflights
第 3 輪 安全區適配 自定義 rules
第 4 輪 簡化常用類名 shortcuts
第 5 輪 動態類名支持 safelist

10.3 下一篇預告

《【AI 編程實戰】第 5 篇:Pinia 狀態管理不會寫?讓 AI 手把手教你最佳實踐》

下一篇繼續展示對話式協作,教你:

  • 如何讓 AI 設計 Store 結構
  • 狀態持久化的對話過程
  • 用戶登入態管理的多輪溝通

與 AI 協作的關鍵不是「寫出完美提示詞」,而是學會和 AI 對話
如果這篇文章對你有幫助,請點讚、收藏!


原文出處:https://juejin.cn/post/7584472215976116239


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝13   💬9   ❤️5
364
🥈
我愛JS
📝1   💬8   ❤️2
61
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付