day13-Trae开发微信小程序02
今日内容
0 回顾项目开发流程
######### 1 标准企业中软件开发流程#####################
# 1 公司立项: 一键换脸微信小程序
# 2 产品经理设计:项目需求,功能
-使用工具,软件:墨刀,制作 原型图--》基本都是黑白的--》展示项目功能和流程
# 3 UI部门设计软件界面
-参照原型图设计---》UI设计图
-美工:PS软件,画图,切图
# 4 分任务,部门开发
-在分部门开发之前--》有个架构说明书做指导
-前端:我们看到的页面--》拼多多小程序
-后端:对前端功能的数据和业务支撑
-后端开发:后端--》项目架构设计会
-订单组
-用户组
-前端开发:小程序
-订单组
-用户组
# 5 测试:软件测试,联调
# 6 运维部门:上线
-服务器---》互联网用户都可以使用
# 7 运营
################# 2 一键换脸微信小程序 ###########
1 微信小程序端: 2 个人
-界面--》UI设计图
2 后端:Python + Django: 2 个人
3 数据库:存储数据
-mysql

1 UI示意图
# 1 美工上场---》设计软件的界面,图片等等
# 2 我们借助于Trae帮我们生成界面图---》可能不会完全符合我们的需求---》需要多次调整
# 3 使用Trae生成UI示意图
三种生成方式:结合起来用
1.1 通过提示词生成
你是一位资深设计师,你非常了解微信小程序的设计风格,拥有丰富的全栈开发经验和极高的审美,擅长设计现代风格的微信小程序端界面
## 我的微信小程序需求是:
我要做一款智能换脸微信小程序,你根据需求分析书,设计出界面
## 我的要求
1.页面元素尽量高级美观,遵循移动端设计规范,注重UI设计细节。
2.所有数据使用假数据,所有页面都可以点击交互。
3.图标使用CDN方式引入。
4.把设计图生成在 目录下,每个子页面都是一个但单独的html,方便在一个页面展示全,index.html里把所有子页面展示出来。
5.界面尺寸模拟IPhone17 Pro,让页面圆角化,使其更像真实微信小程序界面。
6.不要带网络,时间等状态栏。
请按以上要求生成完整的高保真原型图(html)
生成的UI示意图,我们查看后,如果有不满意的地方--》继续跟 Trae交互,让它修改--->直到我们满意即可
1.2 通过手绘图生成
# 1 提示词生成---》界面布局,颜色,功能按钮---》提示中没有描述特别清楚---》好多是大模型自己按自己的想法生成的
# 2 我们想按自己想法做
# 3 提示词 + 手画一个界面图
我想做一个英语单词词汇量测试的小程序,根据这张手绘图,帮我生成首页UI设计,以html形式输出,尽量美观好看一些,你可以有自己的想法加入改动,帮我生成在当前项目目录下。

1.3 通过图片生成
# 1 使用提示词,每次生成的界面样式可能不一样
# 2 如果我们要控制一样--》严格--》使用图片生成
# 3 示意图哪里来?
1 截图别人的软件截图使用
2 找专业美工设计好---》使用设计图,让Trae生成

2 项目架构设计
分前后端部门开发代码
-根据UI示意图--》设计项目功能,用代码实现
后端:python + django
-架构说明书:用什么技术?用什么数据库存数据?密码加密用什么方式?
前端:微信小程序原生开发
-架构说明书
2.1 Django介绍
# 1 Python 编程语言,可以写软件---》用来写 换脸小程序后端
# 2 使用Python编写后端,需要使用一些框架:Web框架---》对外提供API接口
-Django--》Python 界用来写web应用的框架
# 3 框架:
提供了很多基础模块和功能--》我们只需要在固定的位置写python代码,就能实现一个web软件
# 4 开发在本地:使用django开发--》上线要把开发完的django项目,放在服务器上--》所有互联网用户都可以调用
# 5 如果有同学想学django,网上找资料系统学习一下
-我不建议【比较难】

2.2 前后端架构设计提示词
# 1 架构说明书是由公司架构师编写,规定,规范的--》后期开发人员按照这个说明书的要求开发项目
-内部涵盖开发技术,数据库等等
# 2 使用Trae生成---》大家不用改了,如果大家不懂后端和小程序开发,好多技术点大家可能看不懂
根据需求文档和UI设计图,生成项目架构设计文档,包含后端架构文档和微信小程序架构文档
要求:
1.后端使用Python+Django 4 + Mysql8 + DjangoRestFramework等技术实现。
2.微信小程序端使用小程序原生框架。
3.后台管理使用django 自带admin和Simpleui美化。
4.前后端目录结构都一并生成,后端接口格式和参数和返回值格式也生成。
5.后端数据库设计:设计出项目所需表和字段(简要ER图),用户表使用Django自带的User表。
6.以Markdown格式生成并输出。
7.后端文档写入到文件中: 3-架构设计 /1-项目后端架构文档.md。
8.微信小程序文档写入文件: 3-架构设计 /2-微信小程序架构文档.md。
3 后端环境搭建
Trae可以帮我们开发后端项目,但是最好,我们先把环境搭建好
在本地开发--》需要搭建本地的开发环境
直接让Trae写代码,然后写完,我们运行测试即可
3.1 Python环境
# 1 老师用的Python3.13.11
-如果大家会装python解释器---》最好跟我一样
-如果大家不会--》之前装了其他版本,用其他版本也可以--》3.14
# 2 验证一下自己python版本
# 验证-打开cmd,输入
python --version
Python 3.13.11

3.2 Django环境
# 1 Django 环境,可以不用搭建
# 2 Trae会帮我们搭建的
# 3 想搭建:按照如下步骤
1 打开cmd
2 pip install django==4.2
# 4 在我们本地的python解释器上,装了django框架
python3.13+django4.2 ---》就可以开发Django项目了

3.4 Python调用Coze换脸工作流代码
# 1 同学们不需要懂--》是我+AI写的
-纯AI写有bug---》python调用coze工作流--》API是Coze提供的--》有的ai读不到Coze提供的文档--》有时候Coze文档改了--》ai还是用老办法写,就会有bug
-把coze文档的说明网页给AI不行吗?--》》可以解决百分之90的问题
-Coze的官方文档--》可能更新不及时
-
# 2 我之前讲课,写好一版--》能用
-但是后来coze工作流API更新了---》就不能用了
-我调了一下--》改好了---》之前视频的代码是不能用的
-最新的代码才可以
# 3 使用代码之前:
1 获取换脸工作流的id号:7536960050292998154
2 获取令牌:https://www.coze.cn/open/oauth/pats
-pat_jrwsm03uyMusYK15j9Fm7rMLKZ34uslMY5Wl0m0rcsKdm8jlYy40zpi3FV9WZ2TV
3 修改下面代码

import requests
import json
import time
import os
from typing import Optional, Dict, Any
'''
个人访问令牌:https://www.coze.cn/open/oauth/pats
轮询配置说明:
POLL_INTERVAL: 每次查询间隔(秒)
MAX_WAIT_SECONDS: 任务最大等待总时长(秒),超时直接终止
'''
class CozeAPI:
"""Coze API客户端,用于调用Coze的换脸工作流"""
# 轮询全局配置
POLL_INTERVAL = 20 # 每20秒查询一次任务状态
MAX_WAIT_SECONDS = 600 # 最长等待600秒,超时失败
REQUEST_TIMEOUT = 15 # 单次http请求超时时间
def __init__(self, api_key: str = None, workflow_id: str = None):
self.api_key = api_key or ''
self.workflow_id = workflow_id or ''
self.base_url = 'https://api.coze.cn'
self.upload_url = f"{self.base_url}/v1/files/upload"
self.run_url = f"{self.base_url}/v1/workflow/run"
self.headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
}
def _get_save_path(self, task_id: str) -> str:
"""内部方法:生成图片保存路径(精简路径处理逻辑)"""
result_dir = os.path.join('face_swap', 'coze_results')
os.makedirs(result_dir, exist_ok=True)
filename = f"result_{task_id}_{int(time.time())}.jpg"
return os.path.join(result_dir, filename)
def download_image(self, image_url: str, task_id: str) -> Optional[str]:
"""下载图片到本地,返回跨平台路径"""
try:
save_path = self._get_save_path(task_id)
resp = requests.get(image_url, stream=True, timeout=self.REQUEST_TIMEOUT)
resp.raise_for_status()
with open(save_path, 'wb') as f:
for chunk in resp.iter_content(chunk_size=8192):
f.write(chunk)
print(f"图片下载成功: {save_path}")
return save_path.replace('\\', '/')
except Exception as e:
print(f"图片下载失败: {str(e)}")
return None
def upload_file(self, file_path: str) -> str:
"""上传文件到Coze并获取文件ID"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"文件不存在: {file_path}")
try:
print(f"开始上传文件: {file_path}")
upload_header = {'Authorization': f'Bearer {self.api_key}'}
with open(file_path, 'rb') as f:
files = {'file': (os.path.basename(file_path), f)}
resp = requests.post(
self.upload_url,
headers=upload_header,
files=files,
timeout=self.REQUEST_TIMEOUT
)
print(f"上传响应: {resp.status_code} | {resp.text}")
result = resp.json()
if resp.status_code == 200 and result.get('code') == 0 and 'data' in result:
file_id = result['data'].get('id')
if not file_id:
raise Exception(f"未提取到文件ID: {result}")
print(f"文件上传成功,ID: {file_id}")
return file_id
raise Exception(f"文件上传失败: {result}")
except Exception as e:
print(f"文件上传异常: {str(e)}")
raise
def run_workflow(self, source_image: str, target_image: str) -> Dict[str, Any]:
"""运行Coze换脸工作流,异步提交任务,返回task_id"""
try:
# 批量上传文件
source_id, target_id = self.upload_file(source_image), self.upload_file(target_image)
payload = {
"workflow_id": self.workflow_id,
"parameters": {
"face": json.dumps({"file_id": source_id}),
"backend": json.dumps({"file_id": target_id}),
"text": "换脸"
},
"app_id": "",
"is_async": True
}
print(f"调用工作流 {self.workflow_id}...")
resp = requests.post(
self.run_url,
headers=self.headers,
json=payload,
timeout=self.REQUEST_TIMEOUT
)
if resp.status_code != 200:
raise Exception(f"工作流调用失败: {resp.status_code} | {resp.text}")
result = resp.json()
if result.get('code') == 0 and (task_id := result.get('execute_id')):
print(f"工作流调用成功,任务ID: {task_id}")
return {
'code': 0,
'msg': 'success',
'data': {
'task_id': task_id,
'workflow_id': self.workflow_id,
'status': 'pending'
}
}
raise Exception(f"工作流调用失败: {result.get('msg')} | {result}")
except Exception as e:
print(f"工作流调用异常: {str(e)}")
raise
def get_workflow_result(self, task_id: str) -> Dict[str, Any]:
"""单次查询工作流执行结果"""
try:
print(f"查询任务 {task_id} 状态...")
query_url = f"{self.base_url}/v1/workflows/{self.workflow_id}/run_histories/{task_id}"
resp = requests.get(query_url, headers=self.headers, timeout=self.REQUEST_TIMEOUT)
if resp.status_code != 200:
raise Exception(f"查询失败: {resp.status_code} | {resp.text}")
result = resp.json()
if result.get('code') != 0:
raise Exception(f"查询结果失败: {result.get('msg')} | {result}")
# 取第一条任务数据
data_list = result.get('data', [])
if not data_list:
return {'status': 'processing', 'task_id': task_id}
data = data_list[0]
exec_status = data.get('execute_status', '')
if exec_status == 'Success':
return self._parse_success_result(data, task_id)
elif exec_status == 'Fail':
return {
'status': 'failed',
'error_message': data.get('error_reason', '未知执行错误'),
'task_id': task_id
}
# 其余状态统一视为处理中
return {'status': 'processing', 'task_id': task_id}
except Exception as e:
print(f"查询结果异常: {str(e)}")
raise
def wait_workflow_finish(self, task_id: str) -> Dict[str, Any]:
"""
循环轮询等待任务完成
:param task_id: 异步任务ID
:return: 最终任务结果(成功/失败)
"""
start_time = time.time()
while True:
# 判断是否超时
elapsed = time.time() - start_time
if elapsed >= self.MAX_WAIT_SECONDS:
return {
'status': 'timeout',
'error_message': f"任务超时,已等待{self.MAX_WAIT_SECONDS}秒仍未完成",
'task_id': task_id
}
try:
res = self.get_workflow_result(task_id)
status = res.get('status')
if status in ('success', 'failed'):
return res
print(f"任务仍在处理中,已等待{round(elapsed,1)}s,{self.POLL_INTERVAL}s后重新查询...")
except Exception as e:
print(f"本次查询接口出错,跳过本次: {str(e)}")
time.sleep(self.POLL_INTERVAL)
def _parse_success_result(self, data: Dict[str, Any], task_id: str) -> Dict[str, Any]:
"""内部方法:解析成功的任务结果"""
try:
output = json.loads(data.get('output', '{}'))
result_data = json.loads(output.get('Output', '{}'))
image_url = result_data.get('out') # 原来是output,现在变成 out
if not image_url:
return {
'status': 'success',
'message': '任务成功但未返回图片链接',
'task_id': task_id
}
local_path = self.download_image(image_url, task_id)
return {
'status': 'success',
'result_image_url': image_url,
'local_image_path': local_path,
'processing_time': data.get('processing_time', 0),
'task_id': task_id
}
except (json.JSONDecodeError, KeyError) as e:
print(f"解析输出JSON失败: {str(e)}")
return {
'status': 'success',
'message': f'任务执行成功,但解析返回数据异常:{str(e)}',
'task_id': task_id
}
if __name__ == '__main__':
try:
coze_api = CozeAPI()
source_path, target_path = './test_source.jpg', './test_target.jpg'
print("===== 开始测试Coze异步换脸工作流 =====")
# 1. 提交异步任务
run_result = coze_api.run_workflow(source_path, target_path)
print(f"任务提交返回: {run_result}")
if run_result.get('code') == 0:
task_id = run_result['data']['task_id']
print(f"获取任务ID: {task_id}")
# 2. 循环轮询等待任务结束(替换原来固定sleep)
final_result = coze_api.wait_workflow_finish(task_id)
print("\n===== 任务最终结果 =====")
print(final_result)
# 3. 结果分类打印
status = final_result.get('status')
if status == 'success':
print(f"\n✅ 换脸成功!")
print(f"在线图片地址:{final_result['result_image_url']}")
print(f"本地保存路径:{final_result['local_image_path']}")
elif status == 'failed':
print(f"\n❌ 任务执行失败:{final_result['error_message']}")
elif status == 'timeout':
print(f"\n⏰ 任务等待超时:{final_result['error_message']}")
else:
print(f"\n❓ 未知任务状态:{status}")
except Exception as e:
print(f"\n❌ 程序整体异常: {str(e)}")


4 微信小程序学习
# 如果大家想学习---》一套资料给大家
视频:
https://www.bilibili.com/video/BV1WgQdYNERe/
笔记:
https://pan.baidu.com/s/1VTd6S3rJKQ42MRFPsFwaZQ 提取码: bpxa

浙公网安备 33010602011771号