很多教程告訴你「寫好提示詞就能讓 AI 一次給出正確答案」,但現實是:你不可能一開始就知道所有細節。真正高效的 AI 協作,是在對話中逐步明確需求。這篇文章通過一個完整的 UnoCSS 配置案例,展示我和 TRAE SOLO 的真實互動過程——從模糊想法到完整方案,中間經歷了哪些溝通和調整。
這是《AI 編程實戰:TRAE SOLO 全棧開發指南》專欄的第四篇文章,帶你學會如何與 AI 正確的溝通協作。
網上很多 AI 教程會給你看這樣的「完美提示詞」:
幫我配置 UnoCSS,項目環境和需求如下:
【項目環境】UniApp + Vue3 + Vite,目標平台微信小程序
【功能需求】支持 attributify、@apply、圖標、安全區適配
【已知問題】小程序 transform 類需要預設 CSS 變數
【輸出要求】完整的 uno.config.ts 配置文件
然後告訴你:「看,一次就能得到完美答案!」
但問題是:
真實的 AI 協作是一個漸進式對話的過程:
第 1 輪:我有個模糊的需求
↓
AI:給出初步方案 + 執行計劃
↓
第 2 輪:我發現問題 / 補充細節
↓
AI:調整方案
↓
第 3 輪:遇到報錯 / 樣式不生效
↓
AI:排查問題 + 修復
↓
最終:得到完整可用的方案
接下來,我會完整展示和 TRAE SOLO 配置 UnoCSS 的真實對話過程。
剛開始,我對 UnoCSS 的了解很有限,只知道它是「原子化 CSS」。我的第一句話很簡單:
我:項目需要用 UnoCSS,幫我配置一下
TRAE SOLO 沒有直接開始寫代碼,而是先給出了執行計劃:
TRAE SOLO:好的,我來幫你配置 UnoCSS。在開始之前,我需要先了解一些信息:
📋 執行計劃:
1. 分析項目結構,確定技術棧
2. 選擇合適的 UnoCSS 預設
3. 生成配置文件
4. 配置 Vite 插件
🤔 我有幾個問題:
1. 這是什麼類型的項目?(Vue/React/UniApp)
2. 目標運行平台是什麼?(Web/小程序/App)
3. 有沒有特別想要的功能?(圖標/attributify 模式等)
請告訴我這些信息,或者我可以先分析你的項目結構來判斷。
關鍵點:TRAE SOLO 主動詢問上下文,而不是瞎猜。
我:UniApp + Vue3 項目,主要跑微信小程序,也要支持 H5。
功能的話,我也不太清楚,你看著配吧,常用的都加上。
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
是否按這個計劃執行?或者你想調整什麼?
我:可以,就按這個來
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 試試效果。
運行項目後,我發現部分樣式不生效:
我:樣式大部分生效了,但是 translate-x-2 這個類沒效果,
元素沒有移動
TRAE SOLO:讓我檢查一下...
我查看了生成的 CSS,發現 translate-x-2 生成的代碼是:
transform: translateX(var(--un-translate-x));
問題在於:小程序環境沒有預設 --un-translate-x 這個 CSS 變數。
在瀏覽器中,UnoCSS 會通過 :root 選擇器預設這些變數,
但小程序不支持 :root 選擇器。
🔧 修復方案:
在 uno.config.ts 中添加 preflights,手動為小程序元素預設變數。
是否需要我幫你修復?
我:幫我修復吧
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;
/* ... 其他變數 */
}`,
},
],
✅ 已修復,重新運行項目試試。
我:好了,translate 生效了
開發過程中,我發現 iPhone 底部有安全區遮擋內容:
我:iPhone 底部有個橫條會擋住內容,UnoCSS 能處理這個嗎?
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 類了。
我:flex items-center justify-between 每次都要寫這麼長,
有沒有辦法簡化?
TRAE SOLO:可以用 UnoCSS 的 shortcuts 功能,把常用組合定義成短類名。
比如:
- center = flex justify-center items-center
- between = flex justify-between items-center
你想定義哪些快捷方式?或者我根據你的代碼分析常用組合?
我:你分析一下吧,看哪些用得多
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' },
],
是否按這個配置?或者你想調整?
我:可以,就這樣
我:我有個地方根據狀態切換顏色:
<text :class="`text-${status}-500`">狀態</text>
status 可能是 red、green、blue,但樣式不生效
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'],
},
},
})
配置完成後,我開始開發業務組件。同樣是對話式協作:
我:幫我寫一個回复卡片組件,用來展示 AI 生成的回复。
左邊是語氣標籤(比如「高情商」),中間是回复文字,右邊是複製按鈕。
TRAE SOLO:好的,我來幫你開發這個組件。
📋 執行計劃:
1. 創建 ReplyCard.vue 組件
2. 定義 Props:tone(語氣)、text(文本)
3. 定義 Events:copy(複製)
4. 使用 UnoCSS 原子類實現樣式
🤔 幾個問題:
1. 語氣標籤的顏色是固定的還是根據內容變化?
2. 複製按鈕是圖標還是文字?
3. 有沒有設計稿可以參考?
我:標籤顏色根據語氣類型自動變,用哈希算法分配吧。
複製按鈕用圖標。設計稿沒有,你自己設計一個好看的。
TRAE SOLO:明白了,我來實現:
【設計方案】
- 卡片:白色背景、圓角、內邊距
- 標籤:小圓角、根據文字哈希分配 5 種顏色
- 文本:深灰色、支持多行
- 按鈕:圓形點擊區域、圖標居中
開始生成代碼...
<!-- 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>
我:不錯,但我想加一個功能:有時候不需要顯示標籤,能不能加個 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 放在組件內部?
我:你說得對,放父組件更好
| 錯誤做法 | 正確做法 |
|---|---|
| 花 30 分鐘寫一個「完美提示詞」 | 花 1 分鐘說出需求,讓 AI 提問 |
| 一次性想清楚所有細節 | 邊做邊發現問題,逐步完善 |
| 把 AI 當執行工具 | 把 AI 當協作夥伴,可以對話 |
每次提需求後,讓 AI 先給出執行計劃:
我:[需求描述]
AI:📋 執行計劃:
1. xxx
2. xxx
3. xxx
🤔 有幾個問題:
1. xxx?
2. xxx?
確認後我開始執行。
好處:
❌ 錯誤方式:
我:樣式不生效
✅ 正確方式:
我:translate-x-2 這個類在小程序裡不生效,但在 H5 正常。
我看了生成的 CSS,是 transform: translateX(var(--un-translate-x))。
是不是變數沒定義?
當 AI 給出方案時,追問原理:
我:為什麼要用 preflights?直接寫 CSS 不行嗎?
TRAE SOLO:preflights 是 UnoCSS 的預設樣式注入機制,和直接寫 CSS 的區別:
1. preflights 會被注入到所有生成的 CSS 之前,確保優先級正確
2. 可以通過 layer 控制加載順序
3. 統一管理,修改時只需要改配置文件
直接寫 CSS 也可以,但需要確保加載順序正確,否則可能被覆蓋。
好處:理解原理後,下次遇到類似問題可以自己判斷。
| 輪次 | 需求 | 成果 |
|---|---|---|
| 第 1 輪 | 基礎配置 | presets、transformers、theme |
| 第 2 輪 | 修復 transform 問題 | preflights |
| 第 3 輪 | 安全區適配 | 自定義 rules |
| 第 4 輪 | 簡化常用類名 | shortcuts |
| 第 5 輪 | 動態類名支持 | safelist |
《【AI 編程實戰】第 5 篇:Pinia 狀態管理不會寫?讓 AI 手把手教你最佳實踐》
下一篇繼續展示對話式協作,教你:
與 AI 協作的關鍵不是「寫出完美提示詞」,而是學會和 AI 對話。
如果這篇文章對你有幫助,請點讚、收藏!