skip to content
仙人掌主题

全栈天气OOTD小程序:AI生图

/ 21 min read

本期要点:

本期实战我们会开发一个天气+AI生成OOTD的一个小程序,你将掌握:

• 如果使用Cursor快速开发具有交互能力的原型图?

• 如何使用原型图快速用Cursor开发小程序前端?

• 如何用Coze快速开发后端API??

• 接入Coze后端API,完成全栈小程序开发

本期课程环节比较复杂,但是整体不难。相信你跟着下面的视频和文档,能掌握开发这样一个这样的小程序!

效果展示

  1. 可交互原型图
  1. 全栈小程序

生成原型图

提示词:

我需要打造一个实用的天气 + OOTD的小程序,这个小程序的需求如下:
1、有两个tab,第一个tab是「OOTD」,第二个tab是:「我的」
2. 「OOTD」会有3个卡片:今日天气、近7日天气、今日穿搭风格、请你使用合适的动效和icon去表示天气和气温
3. 今日穿搭风格需要用户选择今天的穿搭风格:
- 如果用户在我的输入了男生:['运动休闲风', '商务精英风', '日系潮流风', '韩系简约风', '学院风', '街头嘻哈风', '户外机能风', '复古文艺风', '极简主义风', '工装风']
- 如果用户在我的输入了女生:['甜酷风', '温柔风', '学院风', '韩系简约风', '设计师品牌风', '复古文艺风', '小香风', '森女系', '运动休闲风', 'Y2K风']
4. 在今日穿搭卡片,选择穿搭风格后,用户可点击按钮【生成今日OOTD】,然后从下方弹出一个Popup。Popup会生成AI给的今日穿搭建议,和今天的3张穿衣风格的图片,图片用轮播图显示
5. 我的页面,需要显示:城市、性别、个人描述。这3个在用户首次进入的时候,需要有引导卡片引导用户输入,城市和个人特描述,性别选择。
我现在希望获得高质量的原型设计,请在prototype页面下,通过以下方式协助我完成所有界面的原型图,并确保这些设计稿可直接用于开发环节:
1、用户需求解析:首先分析我产品的完成需求和页面,梳理关键交互路径。
2、页面架构设计:作为产品规划者,确定必要的界面结构,保证信息层级清晰合理。
3、细致UI呈现:从设计师角度出发,创建符合iOS规范的界面,运用现代化设计元素,打造舒适视觉效果。设计风格请参考图片给到的设计风格
4、HTML可交互原型:利用HTML + Tailwind CSS实现所有原型页面,CSS尽可能的采用CSS的类名而不要自己手写,结合FontAwesome(或其他开源图标库)让界面更加精致、接近实际应用效果。
5、 文件组织方式:
每个功能界面应独立成HTML文件,例如:index.html、weather.html、profile.html、ootd.html等。index.html作为原型图的总览页面,不直接包含各界面代码,而是通过iframe方式嵌入各个页面用做预览,并在index页面中直接嵌入各个iframe,展示所有设计,避免页面跳转。
增强真实感:
- 界面尺寸对应iPhone 16 Pro Max,实现圆角边框,模拟真实手机显示效果。
- 采用真实的相关图片和图标,而非简单占位图(可从Unsplash、Pexels等在线图库中选取)。
- 包含微信小程序风格的顶部状态栏及底部导航栏
请按照上述要求提供完整的HTML代码实现,确保代码质量可支持实际开发使用。

**Figma设计垫图参考:**https://www.figma.com/community/file/1394776817954586742

这是最终使用Cursor + Claude3.7的模型生成的原型图参考

创建小程序前端

1. 初始化小程序

打开微信开发者工具,选择最简单的【JS-基础模板】:

• Appld:可使用测试号

• 后端服务:不使用云服务

创建成功后,将项目移动到你的项目目录中,确保和原型图 /prototype 目录保持一致。

为什么要和prototype放到一起?

-这样可以方便使用Cursor直接 @ 对应的html文件,来生成页面的样式

2. 完成 【OOTD】首页

提示词:

请使用 @home.html 去改造 @index.wxml @index.wxss @index.js,我希望样式保持一致。icon先使用emoji

3. 完成【我的】页面

• 创建页面提示词:

请使用 @profile.html , 去实现我的页面,要求:
1. 在 @pages 下创建profile文件夹,并生成对应的小程序代码
2. 样式尽可能保持100%一致
3. 并添加两个页面之间的跳转功能

• 修复问题提示词参考(1)

生成后,我点击【我的】这个tab没法实现跳转

• 修复问题提示词参考(2)

现在有多个问题:
1. 在 @profile.wxml 中我不希望显示微信用户头像,可以隐藏
2. @profile.wxml 中点击城市编辑,我希望也能弹出输入框
3. 底部tab栏的icon没有了,请你添加上对应的emoji,不用使用图片,也无需emoji高亮状态

4. 完成首页引导

提示词:

增加页面逻辑:
1. 如果首页进来的时候,目前在本地存储中没有城市、性别、个人特性,那么需要自动跳转到一个引导页面。该引导页面的样式参考 @onboarding.html,保持100%还原
2. 引导页面的文字填写后,需要保存到本地。并且在 @profile.wxml 中使用
3. @profile.js 我的页面修改编辑信息后,也需要存储到本地

5. 完成OOTD的popup

提示词:

请你根据 @ootd_popup.html 生成OOTD的popup:
1. 在 @index.wxml 中生成今日OOTD后,在当前页面弹出popup
2. 对应的popup和 @ootd_popup.html 样式保持一致
3. 该组件请你在components下生成并且引入

基于Coze创建后端API

1. 创建获取天气的API

1) 节点1:开始

2) 节点2:代码

提示词:

请你帮我编写一个JavaScript函数getDateRange,该函数能够返回一个对象,对象有两个字段startTime和endTime。startTime为当前的日期,endTime当天n+6的日期。日期的格式为YYYY-MM-DD的格式。

代码:

async function main({ params }: Args): Promise<Output> {
function getDateRange() {
// 获取今天的日期
const today = new Date();
// 获取6天后的日期
const sevenDaysLater = new Date(today);
sevenDaysLater.setDate(today.getDate() + 6);
// 格式化日期为YYYY-MM-DD
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
// 返回包含startTime和endTime的对象
return {
startTime: formatDate(today),
endTime: formatDate(sevenDaysLater)
};
}
return getDateRange()
}

3) 节点3: DayWeather

4) 节点4:结束

2. 创建OOTD的API

1) 节点1:开始

2) 节点2:生成穿搭建议

•输入

• 系统提示词:

# Role: 资深个性化穿搭师
## Goals:
1. 根据用户的城市、天气、性别、个人特性、今日穿搭风格情况提供适合的穿搭建议
2. 生成简洁明了且个性化的穿搭建议
## Skills:
1. 熟悉不同风格、体型的穿搭特点和元素
2. 具备创意思维,能够组合不同单品形成协调的穿搭
3. 擅长色彩搭配,能够根据不同风格和忌用色选择合适的颜色组合
4. 能够描述穿搭的整体效果和风格特点
5. 能够根据用户的个人特性调整穿搭建议
## Constrains:
1. 穿搭建议必须符合用户的今日穿搭风格,不用考虑个人特性,并结合天气偏好给出穿搭建议
2. 穿搭建议需包含具体的颜色搭配
3. 需要描述穿搭的整体效果和风格特点
## Examples:
Example:
Input:
城市:北京
天气:{\"condition\":\"晴\",\"humidity\":22,\"predict_date\":\"2025-03-06\",\"temp_high\":13,\"temp_low\":1,\"weather_day\":\"晴\",\"wind_dir_day\":\"北风\",\"wind_dir_night\":\"西南风\",\"wind_level_day\":\"2\",\"wind_level_night\":\"2\"}
性别:男
个人特性:一个阳光帅气的程序员
今日穿搭风格:日系
Output:
{
"advice": "北京今日晴朗但温差大(1-13℃),建议日系简约风格搭配。上身可选米色或浅蓝色宽松针织衫,下身搭配卡其色工装裤或九分牛仔裤。内搭白色T恤增添层次感。外套可选棕色夹克应对早晚凉意。鞋子推荐白色帆布鞋或杏色运动鞋。整体色调温暖明亮,既展现阳光帅气的程序员气质,又符合日系简约美学。"
"personalTrait": {{personalTrait}}
}

• 用户提示词:

城市:{{city}}
天气:{{weather}}
性别:{{gender}}
个人特性:{{personalTrait}}
今日穿搭风格:{{selectedStyle}}

输出

3) 节点3:00TD文生图Prompt

•输入

• 系统提示词

## Role: 精准天气穿搭图片生成器
## Attention:
请仔细分析用户提供的内容,确保生成的图片准确反映这些元素。这对用户的穿搭体验、舒适度和个人形象塑造至关重要。现在面对的用户是一个对穿搭要求很高的时尚达人,请务必认真进行分析,这对我的工作真的很重要。
## Goals:
1. 生成与给定天气条件(如小雨、湿度高)精确匹配的背景环境
2. 准确呈现推荐的穿搭组合,包括所有提到的服装项目和配饰
3. 确保图片整体风格协调,体现用户偏好的风格,并符合现实穿搭场景
4. 展现穿搭的实用性、时尚感和对不同体型的适应性
5. 精确反映用户的个人特征,如体型等
## Skills:
- 精准解读用户提供的详细内容
- 将文字描述转化为视觉元素,包括细微的服装细节和配饰
- 平衡图片中的各个元素,确保整体和谐并突出关键穿搭特点
- 能够根据不同体型特征调整服装的视觉效果
## Constrains:
- 图片必须准确反映给定的天气条件,如小雨、湿度高、晴天等
- 人物穿着必须与穿搭建议完全一致,包括所有提到的服装项目和配饰
- 图片风格应该体现用户偏好的简约minimalist风格
- 要突出展示穿搭的实用性、时尚感和对不同体型的适应性
- 确保图片中的人物特征与用户描述相符
- 热舞
- 输出格式必须遵循指定的结构(OutputFormat)
## Examples:
Example 1:
Input:
今日穿搭建议(OOTD):
基于小雨淅淅、湿度较高的天气、您的个人特征以及简约minimalist风格偏好,我为您推荐以下低调且富有质感的穿搭:
- 上衣:米白色纯棉长袖衬衫,简约的款式,修身的剪裁适合各种体型,柔软的纯棉面料彰显质感。
- 外套:浅灰色防水风衣,长款的设计能够有效抵御小雨,宽松版型很时尚,适合大多数体型。
- 下装:黑色直筒西裤,线条简洁流畅,黑色经典又百搭,能够修饰腿型。
- 鞋子:深棕色皮鞋,款式简约大方,颜色沉稳。
- 配饰:一条窄款的黑色皮带,金属扣设计精致;还有一块简约的银色手表,增添细节感。
整体搭配以米白色、浅灰色、黑色和深棕色为主,避开了禁用的红色、紫色、粉色和橙红。这种素色搭配营造出一种低调内敛又不失品味的氛围,展现出简约风格的特点,整体感觉干净利落。非常适合在小雨天气穿着,既不会过于张扬又能体现您对质感的追求,同时适合不同体型的人。
🧥如果雨比较大,可以带上一把黑色的长柄雨伞,既实用又能和整体穿搭相呼应。💼
Output:
["1. Weather and environment: The sky is cloudy, with a temperature range of 1°C - 15°C. The ground is slightly damp from the earlier rain, and the air has a hint of moisture.2. Main subject (person): A person stands casually, exuding a sense of understated elegance. Their posture is relaxed.3. Clothing details: The person is wearing a fitted, soft cotton, milky white long-sleeved shirt. Over it is a light gray waterproof long trench coat with a loose fit. The lower body is adorned with black straight-cut trousers that have a clean, simple line. On the feet are deep brown leather shoes. A narrow black belt with an精致 metal buckle is around the waist. There is also a simple silver watch on the wrist.4. Background elements: A city street with buildings and people going about their day. The cloudy sky looms above.5. Lighting and atmosphere: The lighting is soft and diffused, as if on a cloudy day. The atmosphere is calm and understated, reflecting the minimalist style.6. Additional details: The person is wearing thick socks to keep warm. The overall look is clean, coordinated, and shows both leisure and fashion. A black long-handled umbrella is held by the side, ready for use if the rain picks up again."]

• 用户提示词

根据用户输入的穿搭建议{{advice}},个人特征{{personalTrait}}给出符合输出格式的图像生成的提示词,我需要3套提示词

输出

4) 节点4:批处理

5) 节点5:批处理体(图像生成)

• 输入

• 提示词

真人实拍
{{prompt}}

• 负向提示词

Sketch, Tattoo, Beard, EasyNegative, Bad Hand, Teeth, Worst quality, Low quality, Normal Quality, Reduced, Normal Quality, Face, Look, Text, Errors, redundant numbers, Fewer Numbers, Cropping, jpeg Artifacts, Signatures, Watermarks, usernames, Blur, Skin Spots, Acne, Skin blemishes, Bad Anatomy, Fat, bad feet, cuts, badly drawn hands, badly drawn faces, mutated, deformed, tilted heads. Bad anatomy. Bad hands, more fingers, less fingers. Extra limbs. Extra arms, extra legs, deformed limbs. Fused fingers. Too many fingers, long neck, opposite eyes, mutated hands, bad body, bad proportions, thick proportions, words, mistakes, missing fingers, missing arms, missing legs, too many fingers, too many arms, too many legs, too many feet, too few fingers,

6) 节点6:结束

3. 测试井写后端接口文档

1). 在Coze中测试API

2).编写接口文档

docs.md:

# 1. 请求天气 API
- 请求方式
```javascript
import { CozeAPI } from "@coze/api";
const apiClient = new CozeAPI({
token: process.env.COZE_TOKEN,
baseURL: "https://api.coze.cn",
});
const res = await apiClient.workflows.runs.stream({
workflow_id: "7479313786055786530",
parameters: {
city: "北京",
},
});
```
- 返回值
```
{"code":0,"cost":"0","data":"{\"output\":[{\"condition\":\"晴\",\"humidity\":45,\"predict_date\":\"2025-03-08\",\"temp_high\":15,\"temp_low\":2,\"weather_day\":\"晴\",\"wind_dir_day\":\"南风\",\"wind_dir_night\":\"南风\",\"wind_level_day\":\"2\",\"wind_level_night\":\"2\"},{\"condition\":\"晴\",\"humidity\":45,\"predict_date\":\"2025-03-09\",\"temp_high\":16,\"temp_low\":7,\"weather_day\":\"晴\",\"wind_dir_day\":\"西南风\",\"wind_dir_night\":\"西南风\",\"wind_level_day\":\"3\",\"wind_level_night\":\"3\"},{\"condition\":\"多云\",\"humidity\":47,\"predict_date\":\"2025-03-10\",\"temp_high\":17,\"temp_low\":7,\"weather_day\":\"多云\",\"wind_dir_day\":\"西南风\",\"wind_dir_night\":\"南风\",\"wind_level_day\":\"2\",\"wind_level_night\":\"2\"},{\"condition\":\"多云\",\"humidity\":49,\"predict_date\":\"2025-03-11\",\"temp_high\":15,\"temp_low\":3,\"weather_day\":\"多云\",\"wind_dir_day\":\"西南风\",\"wind_dir_night\":\"西北风\",\"wind_level_day\":\"2\",\"wind_level_night\":\"2\"},{\"condition\":\"晴\",\"humidity\":14,\"predict_date\":\"2025-03-12\",\"temp_high\":16,\"temp_low\":2,\"weather_day\":\"晴\",\"wind_dir_day\":\"西北风\",\"wind_dir_night\":\"北风\",\"wind_level_day\":\"3\",\"wind_level_night\":\"2\"},{\"condition\":\"多云\",\"humidity\":20,\"predict_date\":\"2025-03-13\",\"temp_high\":14,\"temp_low\":3,\"weather_day\":\"多云\",\"wind_dir_day\":\"东南风\",\"wind_dir_night\":\"东南风\",\"wind_level_day\":\"2\",\"wind_level_night\":\"2\"},{\"condition\":\"多云\",\"humidity\":37,\"predict_date\":\"2025-03-14\",\"temp_high\":11,\"temp_low\":2,\"weather_day\":\"多云\",\"wind_dir_day\":\"东南风\",\"wind_dir_night\":\"东北风\",\"wind_level_day\":\"2\",\"wind_level_night\":\"2\"}]}","debug_url":"https://www.coze.cn/work_flow?execute_id=7479340235975245859&space_id=7331593697773010979&workflow_id=7478968315801763859&execute_mode=2","msg":"Success","token":0}
```
# 2. 生成OOTD
- 请求方式:
```
// Our official coze sdk for JavaScript [coze-js](https://github.com/coze-dev/coze-js)
import { CozeAPI } from '@coze/api';
const apiClient = new CozeAPI({
token: 'pat_1OothP02BM95kEFg6ShHmdA0w2NT9VjcejY8txb3uRCxlwlliSBJF8OFYgJSE0Ob',
baseURL: 'https://api.coze.cn'
});
const res = await apiClient.workflows.runs.stream({
workflow_id: '7479313786055786530',
parameters: {
"city": "北京",
"gender": "男",
"personalTrait": "我是一个呆呆的程序员,但很帅气",
"selectedStyle": "日系",
"weather": {
"condition": "多云",
"humidity": 37,
"predict_date": "2025-03-14",
"temp_high": 11,
"temp_low": 2,
"weather_day": "多云",
"wind_dir_day": "东南风",
"wind_dir_night": "东北风",
"wind_level_day": "2",
"wind_level_night": "2"
}
},
})
```
- 返回值:
```
{"code":0,"cost":"0","data":"{\"advice\":\"北京今日多云,气温2 - 11℃。日系风格的话,可以上身着淡蓝色的长袖衬衫,内搭白色棉质T恤,下身搭配深灰色的直筒休闲裤。鞋子选择米白色的低帮板鞋。再配上一条浅棕色的皮带作为点缀。整体颜色清新淡雅,风格休闲舒适,很符合日系穿搭的简约随性,也适合呆呆又帅气的程序员形象。\",\"files\":[{\"data\":\"https://s.coze.cn/t/SkJKEvWrfyE/\",\"msg\":\"success\"},{\"data\":\"https://s.coze.cn/t/PpueU5MRrSQ/\",\"msg\":\"success\"},{\"data\":\"https://s.coze.cn/t/XFP_8E7LZlo/\",\"msg\":\"success\"}]}","debug_url":"https://www.coze.cn/work_flow?execute_id=7479341443035955210&space_id=7331593697773010979&workflow_id=7479313786055786530&execute_mode=2","msg":"Success","token":2559}
```

接入后端API

1. 接入天气API

• 输入提示词,接入请求天气的API

现在让我们开发后端部分,首先我们来接入天气的api:
1. 在 server/ 目录下初始化express的后端,并且引入.env中的环境变量COZE_TOKEN
2. 参考 @docs.md 中的请求天气 API,node.js后端请求coze的后端
3. 进入首页的时候,请求node.js后端,获取到的值用来渲染首页的2个天气卡片
4. 初始化没有天气的时候,请你给2个天气卡片添加上骨架图的动画效果,并以组件方式引入并渲染

• 优化& 修改bug:

目前请求天气的逻辑有bug,目前我在 @profile.wxml 修改了城市,但是城市的天气没有再次请求刷新,我希望能够使用本地保存的城市信息,并能够更改之后刷新

2. 接入OOTD的API

• 输入提示词,接入请求天气的API

现在我们来开发第二个接口,用于生成用户的OOTD,要求:
1. 创建ootd接口,接口参考 @docs.md 中的生成OOTD
2. 用户在 @index.wxml 中点击【生成今日OOTD】按钮后,打开popup立即请求该接口,参数分别有:city/gender/personalTrait/selectedStyle/weather。需要正确的传递请求参数
3. 给Popup在请求期间添加上合适的骨架图动画,并且以组件的形式引入
  1. 其他优化
@index.wxml 目前今日穿搭风格,男生和女生需要进行去区分,女生和男生的不一样。用户切换性别之后需要进行风格的更改

课程源码:

下载链接