在实际项目开发中,我们经常需要将一些复杂的业务逻辑或创意快速原型化,特别是涉及3D可视化、空间规划这类需要图形学基础的功能。传统开发流程需要前端、后端、3D引擎工程师紧密协作,周期长、门槛高。Zcode作为一个新兴的AI辅助开发平台,其核心价值在于能够理解自然语言描述,并生成可运行的代码,这为快速构建3D应用原型提供了全新的可能性。
本文面向有一定编程基础,但对Three.js、WebGL等3D开发技术不熟悉,或希望极大提升3D应用开发效率的开发者。我们将以“复刻一个3D空间规划应用”为目标,全程使用Zcode作为核心工具。你将学习到如何通过Zcode CLI与Web界面结合,将一句简单的需求描述,逐步转化为一个具备基础3D场景、可交互物体、简单布局规划功能的Web应用。整个过程不仅会展示Zcode的使用技巧,更会深入解释生成的代码结构、关键配置参数以及如何调试和扩展,确保你获得一个可学习、可复现、可二次开发的项目。
1. 理解Zcode与3D空间规划应用的技术栈
在动手之前,必须厘清我们使用的工具链和最终产物的技术构成。这有助于理解Zcode在整个流程中的定位,以及当生成结果不完美时,我们应该从哪个层面进行干预和调整。
1.1 Zcode是什么:AI驱动的代码生成与工程化平台
Zcode并非一个单一的代码生成模型,而是一个集成了大语言模型能力的开发平台。它通常包含Web交互界面和命令行工具(CLI)。你可以通过自然语言向它描述需求,它会生成相应的代码片段、配置文件甚至完整的项目脚手架。对于“复刻3D空间规划应用”这类综合性任务,Zcode的优势在于能快速整合多个技术模块,例如前端框架、3D渲染库、UI组件和基础交互逻辑,省去了大量查阅文档和手动拼接的时间。
注意:Zcode生成的代码是“起点”而非“终点”。它基于常见的开源库和最佳实践模式生成,但可能不完全符合你的具体业务逻辑或性能要求。因此,理解其生成的代码至关重要。
1.2 3D空间规划应用的核心技术组件
一个基础的3D空间规划应用,通常由以下几层构成:
- 3D渲染引擎:在浏览器中渲染3D场景。Zcode最可能选用的是Three.js,因为它是目前最流行、社区最活跃的Web端3D库,学习资源和示例丰富。
- 前端框架:用于组织应用结构、状态管理和构建UI。常见选择是React、Vue或纯JavaScript。Zcode根据上下文可能选择React,因其生态完善,组件化思想清晰。
- UI组件库:提供按钮、滑块、菜单等界面元素。可能会使用Ant Design、Material-UI或更轻量的库。
- 交互与逻辑:实现物体的拖拽、旋转、缩放,以及布局数据的计算与存储。
- 构建工具:如Vite或Webpack,用于打包和开发服务器。
Zcode的任务就是将你对这些层的需求,用正确的依赖、配置和示例代码组合起来。
1.3 明确我们的目标:一个最小可行产品(MVP)
为了避免需求过于宽泛导致Zcode生成无用代码,我们需要将“3D空间规划应用”具体化。本文的目标是构建一个具有以下功能的Web应用:
- 一个3D场景视图(Canvas)。
- 场景中预置几种简单的3D几何体(如立方体、球体、圆柱体),代表不同的家具或设备。
- 可以通过UI面板选择物体,并将其添加到场景中。
- 支持用鼠标拖拽物体,在场景地面(一个平面)上移动位置。
- 一个简单的“重置”按钮,可以清空所有添加的物体。
这个MVP涵盖了3D渲染、物体管理、用户交互等核心概念,是理解和扩展更复杂功能(如旋转、缩放、碰撞检测、数据导出)的完美基础。
2. 环境准备与Zcode CLI初始化
我们将采用Zcode CLI结合其Web能力的混合工作流。CLI用于快速创建项目骨架和文件,Web界面用于复杂的代码生成和对话调试。
2.1 基础开发环境配置
首先,确保你的本地机器已安装以下必备工具:
| 工具 | 推荐版本 | 验证命令 | 作用 |
|---|---|---|---|
| Node.js | 18.x 或 20.x (LTS) | node --version | JavaScript运行时,提供npm/npx/yarn等包管理工具。 |
| npm | 随Node.js安装 | npm --version | Node.js包管理器,用于安装依赖。 |
| Git | 最新版 | git --version | 版本控制,也用于克隆模板。 |
| 代码编辑器 | VS Code | - | 编辑和查看生成的代码。 |
如果尚未安装Node.js,请从其官网下载LTS版本并安装。安装后,在终端中运行上述验证命令确认安装成功。
2.2 安装与配置Zcode CLI
Zcode CLI是与Zcode平台交互的命令行工具。根据其官方文档,通常可以通过npm全局安装。
# 假设Zcode CLI的npm包名为 @zcode/cli npm install -g @zcode/cli安装完成后,验证安装并登录(如果需要):
zcode --version # 如果需要认证,可能需要运行(具体命令请以官方文档为准) zcode login注意:
@zcode/cli是一个示例包名。请务必查阅Zcode官方文档或根据网络搜索材料中提到的zcode cli、opencode zcode等关键词,找到正确的安装命令。可能是npm install -g zcode或其他。
2.3 创建项目目录并初始化
我们不直接从零开始描述,而是让Zcode基于一个更明确的上下文生成代码。首先创建一个干净的项目目录。
# 1. 创建一个新的项目文件夹 mkdir 3d-space-planner && cd 3d-space-planner # 2. 初始化一个package.json文件(Zcode生成代码时需要此文件来理解项目结构) npm init -y现在,你的项目根目录下应该有一个package.json文件。接下来,我们需要为Zcode提供更丰富的上下文。创建一个简单的提示文件或直接使用CLI命令。
方法A:使用Zcode CLI的生成命令如果CLI支持直接生成项目,可以尝试:
zcode generate project --template web-3d --name “3d-space-planner”方法B:与Zcode Web界面协同(推荐)更实际的做法是,在Zcode的Web界面中描述详细需求,然后将生成的代码文件复制到本地项目,或使用CLI从Web界面拉取代码。
- 在Zcode Web界面中,新建一个对话或项目。
- 输入详细的提示词(Prompt)。
3. 编写有效的Zcode提示词(Prompt)生成核心代码
与Zcode交互的核心是编写清晰、结构化、分步骤的提示词。以下是一个高效生成我们目标应用的提示词示例。你可以直接在Zcode的Web界面聊天框中输入。
请帮我创建一个基于React和Three.js的3D空间规划Web应用。 项目要求: 1. 技术栈:使用React + TypeScript + Vite作为构建工具。使用Three.js作为3D引擎。 2. 核心功能: - 一个全屏的3D Canvas渲染场景。 - 场景包含一个灰色的网格地面(GridHelper)和一个坐标轴辅助(AxesHelper)。 - 有一个侧边栏UI,包含几个按钮:“添加立方体”、“添加球体”、“添加圆柱体”、“重置场景”。 - 点击“添加立方体”等按钮,会在场景中心位置(0,1,0)创建一个对应的Three.js几何体(Mesh),并赋予随机颜色。 - 鼠标可以拖拽场景中添加的这些物体,限制在网格地面上移动(Y轴位置不变)。 - 点击“重置场景”会移除所有用户添加的物体,恢复初始状态。 3. 代码结构清晰,将3D场景逻辑封装在独立的组件(如`Scene`组件)中,UI逻辑在`App`组件中。 4. 请提供完整的代码文件列表,包括`index.html`, `main.tsx`, `App.tsx`, `Scene.tsx`, `vite.config.ts`以及`package.json`中的关键依赖。 5. 在代码中添加必要的注释,解释Three.js对象创建和事件绑定的关键步骤。3.1 分析提示词结构与Zcode的预期行为
这份提示词之所以有效,是因为它包含了:
- 技术栈锁定:明确指定了React、TypeScript、Vite、Three.js,避免了Zcode猜测技术选型。
- 功能描述结构化:将功能点分条列出,逻辑清晰。
- 具体细节:提到了
GridHelper、AxesHelper、创建位置(0,1,0)、随机颜色、拖拽限制等具体参数,让生成结果更可控。 - 项目结构要求:要求了文件列表和组件分离,有助于生成可维护的代码。
- 附加要求:要求添加注释,这对学习生成的代码非常有帮助。
Zcode在接收到这个提示后,可能会:
- 生成一个包含
package.json依赖描述的文本。 - 逐个生成上述要求的文件内容。
- 可能会解释如何运行项目。
3.2 处理Zcode的生成结果并创建本地文件
假设Zcode在Web界面中给出了如下回复(这里以模拟的关键代码片段为例):
1. package.json 依赖部分
{ "name": "3d-space-planner", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "tsc && vite build", "preview": "vite preview" }, "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "three": "^0.164.0" }, "devDependencies": { "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", "@types/three": "^0.164.0", "@vitejs/plugin-react": "^4.0.0", "typescript": "^5.0.0", "vite": "^5.0.0" } }2. Scene.tsx 核心3D场景组件
import React, { useRef, useEffect, useState } from 'react'; import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; interface SceneProps { objects: THREE.Object3D[]; onObjectAdded: (obj: THREE.Object3D) => void; } const Scene: React.FC<SceneProps> = ({ objects, onObjectAdded }) => { const mountRef = useRef<HTMLDivElement>(null); const sceneRef = useRef<THREE.Scene | null>(null); const rendererRef = useRef<THREE.WebGLRenderer | null>(null); const cameraRef = useRef<THREE.PerspectiveCamera | null>(null); const controlsRef = useRef<OrbitControls | null>(null); const raycasterRef = useRef<THREE.Raycaster>(new THREE.Raycaster()); const mouseRef = useRef<THREE.Vector2>(new THREE.Vector2()); const [selectedObject, setSelectedObject] = useState<THREE.Object3D | null>(null); // 初始化场景 useEffect(() => { if (!mountRef.current) return; const scene = new THREE.Scene(); scene.background = new THREE.Color(0xf0f0f0); sceneRef.current = scene; const camera = new THREE.PerspectiveCamera(75, mountRef.current.clientWidth / mountRef.current.clientHeight, 0.1, 1000); camera.position.set(5, 5, 5); camera.lookAt(0, 0, 0); cameraRef.current = camera; const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(mountRef.current.clientWidth, mountRef.current.clientHeight); mountRef.current.appendChild(renderer.domElement); rendererRef.current = renderer; // 添加光源 const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(10, 20, 5); scene.add(directionalLight); // 添加网格地面和坐标轴 const gridHelper = new THREE.GridHelper(20, 20); scene.add(gridHelper); const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); // 轨道控制器 const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controlsRef.current = controls; // 动画循环 const animate = () => { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); }; animate(); // 窗口大小调整 const handleResize = () => { if (!mountRef.current || !camera || !renderer) return; camera.aspect = mountRef.current.clientWidth / mountRef.current.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(mountRef.current.clientWidth, mountRef.current.clientHeight); }; window.addEventListener('resize', handleResize); // 点击与拖拽事件 const onMouseDown = (event: MouseEvent) => { if (!camera || !scene) return; mouseRef.current.x = (event.clientX / window.innerWidth) * 2 - 1; mouseRef.current.y = -(event.clientY / window.innerHeight) * 2 + 1; raycasterRef.current.setFromCamera(mouseRef.current, camera); const intersects = raycasterRef.current.intersectObjects(objects, true); if (intersects.length > 0) { setSelectedObject(intersects[0].object); } }; const onMouseMove = (event: MouseEvent) => { if (!selectedObject || !camera) return; // 简化版拖拽:将物体移动到鼠标射线与地面平面的交点 mouseRef.current.x = (event.clientX / window.innerWidth) * 2 - 1; mouseRef.current.y = -(event.clientY / window.innerHeight) * 2 + 1; raycasterRef.current.setFromCamera(mouseRef.current, camera); const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); // Y=0 的地面平面 const intersectionPoint = new THREE.Vector3(); raycasterRef.current.ray.intersectPlane(plane, intersectionPoint); selectedObject.position.set(intersectionPoint.x, selectedObject.position.y, intersectionPoint.z); }; const onMouseUp = () => { setSelectedObject(null); }; window.addEventListener('mousedown', onMouseDown); window.addEventListener('mousemove', onMouseMove); window.addEventListener('mouseup', onMouseUp); return () => { window.removeEventListener('resize', handleResize); window.removeEventListener('mousedown', onMouseDown); window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); if (mountRef.current && renderer) { mountRef.current.removeChild(renderer.domElement); } renderer?.dispose(); }; }, []); // 空依赖数组,仅初始化一次 // 当objects变化时,更新场景中的物体 useEffect(() => { if (!sceneRef.current) return; // 移除所有非辅助物体(网格、坐标轴) const toRemove = sceneRef.current.children.filter(child => !(child instanceof THREE.GridHelper) && !(child instanceof THREE.AxesHelper) && !(child instanceof THREE.Light) ); toRemove.forEach(obj => sceneRef.current?.remove(obj)); // 添加新的物体 objects.forEach(obj => sceneRef.current?.add(obj)); }, [objects]); return <div ref={mountRef} style={{ width: '100%', height: '100vh' }} />; }; export default Scene;3. App.tsx 主组件与UI逻辑
import React, { useState } from 'react'; import './App.css'; import Scene from './Scene'; import * as THREE from 'three'; function App() { const [sceneObjects, setSceneObjects] = useState<THREE.Object3D[]>([]); const createRandomColor = () => { return Math.floor(Math.random() * 0xffffff); }; const handleAddCube = () => { const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshStandardMaterial({ color: createRandomColor() }); const cube = new THREE.Mesh(geometry, material); cube.position.set(0, 0.5, 0); // 放在地面上方 setSceneObjects(prev => [...prev, cube]); }; const handleAddSphere = () => { const geometry = new THREE.SphereGeometry(0.5, 32, 16); const material = new THREE.MeshStandardMaterial({ color: createRandomColor() }); const sphere = new THREE.Mesh(geometry, material); sphere.position.set(0, 0.5, 0); setSceneObjects(prev => [...prev, sphere]); }; const handleAddCylinder = () => { const geometry = new THREE.CylinderGeometry(0.5, 0.5, 1, 32); const material = new THREE.MeshStandardMaterial({ color: createRandomColor() }); const cylinder = new THREE.Mesh(geometry, material); cylinder.position.set(0, 0.5, 0); setSceneObjects(prev => [...prev, cylinder]); }; const handleReset = () => { setSceneObjects([]); }; return ( <div className="app-container"> <div className="sidebar"> <h2>3D空间规划</h2> <button onClick={handleAddCube}>添加立方体</button> <button onClick={handleAddSphere}>添加球体</button> <button onClick={handleAddCylinder}>添加圆柱体</button> <button onClick={handleReset} style={{ marginTop: '20px', backgroundColor: '#ff6b6b' }}> 重置场景 </button> <div className="hint"> <p>提示:</p> <ul> <li>点击物体可以选中</li> <li>拖动鼠标可移动选中物体</li> <li>使用鼠标滚轮缩放,右键拖动旋转视图</li> </ul> </div> </div> <div className="scene-container"> <Scene objects={sceneObjects} onObjectAdded={(obj) => setSceneObjects(prev => [...prev, obj])} /> </div> </div> ); } export default App;4. 其他文件Zcode还应生成vite.config.ts、index.html、main.tsx、App.css等文件。你需要将这些代码片段分别保存到本地项目对应的文件中。
操作步骤:
- 在
3d-space-planner项目根目录,根据Zcode生成的package.json内容,更新或创建该文件。 - 创建
src文件夹,并在其中创建App.tsx、Scene.tsx、main.tsx、App.css等文件,将对应代码粘贴进去。 - 在根目录创建
vite.config.ts和index.html。
4. 项目运行、验证与关键代码解析
4.1 安装依赖并启动开发服务器
在项目根目录(包含package.json的目录)下,运行以下命令:
# 安装所有依赖包 npm install # 启动Vite开发服务器 npm run dev如果一切顺利,终端会输出本地服务器地址(通常是http://localhost:5173)。在浏览器中打开此地址。
4.2 验证功能
在打开的网页中,你应该看到:
- 左侧有一个侧边栏,包含四个按钮。
- 右侧是一个占据大部分屏幕的3D场景,其中有灰色网格和红绿蓝坐标轴。
- 点击“添加立方体”、“添加球体”、“添加圆柱体”按钮,场景中心会出现对应形状、随机颜色的物体。
- 点击一个物体(可能会看到其轮廓高亮或控制台有日志,取决于Zcode生成的交互细节),然后按住鼠标拖动,物体应能在地面上移动。
- 点击“重置场景”,所有添加的物体应消失。
4.3 关键代码解析与调整
Zcode生成的代码是一个很好的起点,但其中可能包含需要你理解和优化的地方。
1. 拖拽逻辑的简化与问题上面Scene.tsx中的拖拽逻辑是一个极简实现。它通过鼠标事件和射线检测来实现,但可能存在以下问题:
- 性能:
onMouseMove在鼠标移动时频繁触发,可能造成性能压力。 - 精度:简单的射线与平面求交,在相机角度很大时可能不准确。
- 体验:没有视觉反馈(如被选中物体的高亮)。
一个更健壮的方案是使用Three.js的官方拖拽库(如three-interactive)或更复杂的自定义逻辑。但作为MVP,当前代码足以演示原理。
2. 物体管理策略当前,物体状态(sceneObjects)存储在App组件的React状态中。Scene组件通过useEffect监听这个状态变化,并同步到Three.js场景中。这是一种React状态驱动Three.js场景的常见模式,清晰地将数据(状态)与渲染(Three.js)分离。
3. 内存管理注意Scene组件useEffect的清理函数:它移除了事件监听器、从DOM中移除Canvas、并调用了renderer.dispose()。这对于防止内存泄漏至关重要。如果Zcode没有生成这些清理代码,你需要手动添加。
4. 类型安全项目使用了TypeScript,并且从@types/three导入了类型定义。这使得在编写Three.js代码时可以获得良好的类型提示和错误检查。
5. 常见问题排查与调试
即使使用Zcode生成代码,在运行和扩展过程中也必然会遇到问题。以下是基于此项目的典型排查路径。
5.1 项目无法启动(npm run dev报错)
| 问题现象 | 可能原因 | 检查与解决 |
|---|---|---|
Error: Cannot find module ‘xxx’ | 1. 依赖未安装。 2. package.json中依赖名称或版本错误。3. Node_modules 损坏。 | 1. 运行npm install。2. 核对 package.json中依赖名与Zcode生成的是否一致(如three不是three.js)。3. 删除 node_modules和package-lock.json,重新运行npm install。 |
SyntaxError或类型错误 | 1. TypeScript配置 (tsconfig.json) 不兼容。2. 生成的代码中存在ESLint或TS语法错误。 | 1. 检查Zcode是否生成了tsconfig.json,如果没有,可以从Vite React TS模板中复制一个基础的。2. 在终端运行 npx tsc --noEmit检查TypeScript错误,根据报错修改代码。 |
| 端口被占用 | 默认端口5173已被其他程序使用。 | 终端会提示,可按提示按h查看帮助,或修改vite.config.ts中的server.port配置。 |
5.2 3D场景显示异常
| 问题现象 | 可能原因 | 检查与解决 |
|---|---|---|
| 一片空白,没有网格和坐标轴 | 1. Canvas元素尺寸为0。 2. 相机位置不对,物体在视锥体外。 3. 渲染器没有成功添加到DOM。 | 1. 检查Scene.tsx中mountRef对应的div样式是否为width: 100%; height: 100vh;。2. 检查相机 position和lookAt参数。3. 在浏览器开发者工具中检查Canvas元素是否存在及其尺寸。 |
| 物体是黑色的 | 场景中没有光源,或光源强度太低。 | 检查Scene.tsx中AmbientLight和DirectionalLight是否已创建并添加到场景,尝试增加光源强度。 |
| 拖拽功能无效 | 1. 事件监听器未正确绑定。 2. 射线检测(Raycaster)的目标对象数组 objects为空或错误。3. 选中的物体 selectedObject状态未更新。 | 1. 在浏览器控制台查看是否有JavaScript错误。 2. 在 onMouseDown函数中添加console.log(intersects),检查点击时是否检测到物体。3. 确认传递给 Scene组件的objectsprop是正确的状态数组。 |
5.3 性能问题
- 添加物体过多导致卡顿:每次添加物体都会触发React状态更新和场景重绘。对于大量物体,应考虑使用
THREE.InstancedMesh进行实例化渲染,或使用引用(useRef)直接管理Three.js对象,避免频繁的React重渲染。 - 鼠标移动拖拽卡顿:
onMouseMove事件触发频率极高。可以尝试使用requestAnimationFrame节流,或者只在鼠标按下且选中物体时才监听mousemove事件(当前代码已实现)。
6. 从MVP扩展到完整空间规划应用
基于Zcode生成的这个MVP,你可以通过继续与Zcode对话或手动编码,逐步添加更复杂的功能,使其更接近一个真正的空间规划工具。
6.1 功能扩展清单与Zcode提示词建议
| 扩展功能 | 技术要点 | 给Zcode的提示词建议 |
|---|---|---|
| 物体旋转与缩放 | 在UI上添加按钮或使用键盘快捷键(如R键旋转,S键缩放),修改选中物体的rotation和scale属性。 | “请在我的3D空间规划应用基础上,增加对选中物体的旋转和缩放功能。在侧边栏添加‘旋转’和‘缩放’按钮,点击后通过鼠标拖拽来调整。” |
| 导入外部3D模型 | 使用THREE.GLTFLoader加载.gltf或.glb格式的模型文件。 | “如何修改代码,使其能够从本地文件或URL加载GLB格式的3D模型(如椅子、桌子)并添加到场景中?” |
| 布局保存与加载 | 将场景中物体的position、rotation、scale、geometry类型、material颜色等序列化为JSON,保存到本地或后端。 | “请添加功能,将当前场景中的所有物体状态保存为一个JSON文件,并能从JSON文件加载恢复场景。” |
| 碰撞检测 | 使用THREE.Box3或物理引擎(如cannon-es)计算物体边界框是否相交。 | “我想在拖拽物体时实现简单的碰撞检测,防止两个物体重叠。请指导我如何计算两个Three.js Mesh的边界框(BoundingBox)并检测碰撞。” |
| 多楼层/层级 | 引入“楼层”概念,通过切换不同场景或调整物体可见性来实现。 | “扩展应用以支持多楼层规划。添加一个楼层选择器,切换时显示不同楼层的物体集合。” |
6.2 生产环境考量
如果计划将此类应用部署到生产环境,仅靠Zcode生成的代码是不够的,还需要考虑:
- 代码优化与打包:使用Vite进行生产构建 (
npm run build),对代码进行压缩、分包,确保加载速度。 - 3D模型优化:对导入的3D模型进行减面、压缩纹理处理,使用Draco压缩等。
- 状态管理:当应用复杂时(如上百个物体、复杂UI),考虑引入状态管理库(Zustand, Redux Toolkit)。
- 错误边界与加载态:为React组件添加错误边界(Error Boundaries),为异步加载的模型添加加载指示器。
- 后端集成:布局数据需要持久化时,需要搭建后端API(如使用Node.js + Express)和数据库。
6.3 调试技巧
- 使用Three.js Inspector:在浏览器控制台引入
three.js后,可以使用scene变量直接查看和修改场景中的对象,是强大的调试工具。 - 善用React DevTools:检查组件状态(
sceneObjects)是否正确更新。 - 控制台日志:在关键函数(如事件处理、状态更新)中添加
console.log,跟踪程序执行流。
通过以上步骤,你不仅使用Zcode“一句话”生成了一个3D空间规划应用的骨架,更重要的是理解了其背后的代码结构、Three.js与React的集成方式、以及如何调试和扩展。这正是将AI生成代码转化为实际可掌控、可演进项目的关键。接下来,你可以针对上述任何一个扩展功能,继续向Zcode提出更具体的需求,迭代你的应用。