用 DeepSeek 做前端开发:Vue 3 + Element Plus 全栈实战
·
本文是《DeepSeek 辅助编程实战》系列第 5 篇(完结篇),演示如何用 DeepSeek 实现航次计划系统的前端页面,包括项目搭建、4 个核心页面开发和前后端联调。
一、前端技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| Vue 3 | 3.4 | 前端框架(Composition API) |
| Element Plus | 2.7 | UI 组件库 |
| Vue Router | 4.3 | 路由管理 |
| Axios | 1.6 | HTTP 客户端 |
| Vite | 5.2 | 构建工具 |
| dayjs | 1.11 | 日期处理 |
选择 Element Plus 的理由:
- 企业级中后台组件丰富(表格、表单、对话框)
- 中文文档完善,社区活跃
- 与 Vue 3 Composition API 完美配合
二、项目搭建
2.1 初始化项目
我的 Prompt:
请用 Vite 创建 Vue 3 + Element Plus 前端项目,要求:
1. 项目名:voyage-plan-frontend
2. 依赖:vue 3.4, element-plus 2.7, vue-router 4.3, axios 1.6, dayjs 1.11
3. 开发服务器端口:3000
4. API 代理:/api → http://localhost:5000
5. Element Plus 中文国际化
请给出 package.json、vite.config.js 和 main.js。
package.json:
{
"name": "voyage-plan-frontend",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.4.0",
"element-plus": "^2.7.0",
"vue-router": "^4.3.0",
"axios": "^1.6.0",
"dayjs": "^1.11.0",
"@element-plus/icons-vue": "^2.3.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.0",
"vite": "^5.2.0"
}
}
vite.config.js:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true
}
}
}
})
main.js:
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(ElementPlus, { locale: zhCn })
app.use(router)
// 注册所有图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.mount('#app')
2.2 项目结构
frontend/
├── index.html
├── package.json
├── vite.config.js
└── src/
├── main.js # 入口
├── App.vue # 根组件(布局)
├── router/
│ └── index.js # 路由配置
├── api/
│ └── voyagePlan.js # API 客户端
└── views/
├── PlanList.vue # 列表页
├── PlanDetail.vue # 详情页
├── PlanCreate.vue # 创建页
└── PlanEdit.vue # 编辑页
三、核心页面开发
3.1 应用布局(App.vue)
我的 Prompt:
请用 Element Plus 实现应用布局:
1. 顶部 Header:
- 系统名称:"航次计划编制系统"
- 蓝色渐变背景
- 白色文字
2. 左侧 Sidebar:
- 菜单项:计划列表、新建计划
- 使用 el-menu 组件
- 可折叠
3. 主内容区:
- router-view 渲染子页面
- 适当的内边距
使用 Vue 3 <script setup> 语法。
<template>
<el-container class="app-container">
<el-header class="app-header">
<h1>航次计划编制系统</h1>
</el-header>
<el-container>
<el-aside width="200px" class="app-aside">
<el-menu :default-active="route.path" router>
<el-menu-item index="/">
<el-icon><List /></el-icon>
<span>计划列表</span>
</el-menu-item>
<el-menu-item index="/create">
<el-icon><Plus /></el-icon>
<span>新建计划</span>
</el-menu-item>
</el-menu>
</el-aside>
<el-main class="app-main">
<router-view />
</el-main>
</el-container>
</el-container>
</template>
<style>
.app-header {
background: linear-gradient(135deg, #1e3a5f 0%, #2c5f8a 100%);
color: white;
display: flex;
align-items: center;
}
.app-header h1 { margin: 0; font-size: 20px; }
.app-aside { background: #fff; border-right: 1px solid #e6e6e6; }
.app-main { background: #f5f7fa; padding: 20px; }
</style>
3.2 API 客户端
我的 Prompt:
请用 Axios 封装 API 客户端,要求:
1. baseURL: /api/v1/voyage-plans
2. 响应拦截器:提取 data,统一错误处理
3. 导出所有 API 方法:
- getAll() / getById(id) / getByPlanNumber(num)
- getByVessel(name) / getByStatus(status)
- create(data) / update(id, data)
- issue(id, data) / initiateChange(id, data)
- completeChange(id, changedBy) / cancel(id, data)
// api/voyagePlan.js
import axios from 'axios'
const api = axios.create({
baseURL: '/api/v1/voyage-plans',
timeout: 10000,
headers: { 'Content-Type': 'application/json' }
})
// 响应拦截器
api.interceptors.response.use(
response => response.data,
error => {
const msg = error.response?.data?.message || '请求失败'
return Promise.reject(new Error(msg))
}
)
export default {
getAll: () => api.get(''),
getById: (id) => api.get(`/${id}`),
getByPlanNumber: (planNumber) => api.get(`/number/${planNumber}`),
getByVessel: (vesselName) => api.get(`/vessel/${vesselName}`),
getByStatus: (status) => api.get(`/status/${status}`),
create: (data) => api.post('', data),
update: (id, data) => api.put(`/${id}`, data),
issue: (id, data) => api.post(`/${id}/issue`, data),
initiateChange: (id, data) => api.post(`/${id}/initiate-change`, data),
completeChange: (id, changedBy) => api.post(`/${id}/complete-change?changedBy=${changedBy}`),
cancel: (id, data) => api.post(`/${id}/cancel`, data),
}
3.3 列表页(PlanList.vue)
我的 Prompt:
请用 Element Plus 实现航次计划列表页:
1. 顶部操作栏:
- 状态筛选下拉框(全部/草稿/已发布/变更中/已取消)
- 新建计划按钮
2. 表格列:
- 计划编号、航次名称、船舶名称、起始港、目的港
- 版本(V1, V2...)
- 状态(Tag 标签,不同颜色)
- 总航程
- 创建时间
- 操作列:详情/编辑/发布/变更/取消
3. 操作按钮根据状态显示:
- 草稿:编辑、发布
- 已发布:变更
- 非取消:取消
4. 操作确认:
- 发布:确认对话框
- 变更/取消:输入原因
使用 Vue 3 <script setup> + Composition API。
核心代码片段:
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>航次计划列表</span>
<div>
<el-select v-model="statusFilter" placeholder="按状态筛选" clearable @change="loadData">
<el-option label="草稿" value="Draft" />
<el-option label="已发布" value="Issued" />
<el-option label="变更中" value="Changing" />
<el-option label="已取消" value="Cancelled" />
</el-select>
<el-button type="primary" @click="$router.push('/create')">
<el-icon><Plus /></el-icon> 新建计划
</el-button>
</div>
</div>
</template>
<el-table :data="plans" v-loading="loading" stripe>
<el-table-column prop="planNumber" label="计划编号" width="180" />
<el-table-column prop="voyageName" label="航次名称" />
<el-table-column prop="vesselName" label="船舶名称" width="120" />
<el-table-column label="状态" width="100">
<template #default="{ row }">
<el-tag :type="statusTagType(row.status)" effect="dark" size="small">
{{ row.statusDisplay }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="$router.push(`/detail/${row.id}`)">详情</el-button>
<el-button link type="success" v-if="row.status === 'Draft'" @click="handleIssue(row)">发布</el-button>
<el-button link type="danger" v-if="row.status !== 'Cancelled'" @click="handleCancel(row)">取消</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</template>
3.4 详情页(PlanDetail.vue)
我的 Prompt:
请实现航次计划详情页,使用 Element Plus 组件展示:
1. 页面头部:返回按钮 + 计划编号 + 状态标签
2. 信息分区(el-card):
- 基本信息:el-descriptions 展示编号、名称、船舶、版本、时间等
- 港口信息:起始港/目的港并排展示
- 航线段:el-table 展示各航段详情
- 风险评估:el-statistic 展示四维度评分 + 综合风险等级
- 燃油估算:el-descriptions 展示消耗量、安全系数等
- 应急预案:联系人、电话、备用港口
3. 底部操作按钮:
- 根据当前状态显示可用操作
使用 el-page-header 作为页面头部。
3.5 创建页(PlanCreate.vue)
我的 Prompt:
请实现航次计划创建表单页,要求:
1. 分区表单(多个 el-card):
- 基本信息:航次名称、船舶名称、航次编号、出发/到达时间、创建人
- 港口信息:起始港(UN/LOCODE、名称、国家)、目的港
- 航线段:动态添加/删除航段(el-button + v-for)
- 风险评估:4 个维度评分(el-input-number, 0-100)
- 燃油估算:IFO/MGO 消耗、安全系数
- 应急预案:联系人、电话、备用港口
2. 表单校验:
- 必填字段:航次名称、船舶名称、港口代码/名称、创建人
- 日期校验:到达时间 > 出发时间
3. 提交后跳转到详情页
航线段使用动态行,每行包含:起点、终点、距离、航速、时间、IFO、MGO、说明。
动态航线段的核心实现:
<el-card shadow="never">
<template #header>
<div class="section-header">
<span>航线段</span>
<el-button type="primary" size="small" @click="addSegment">
<el-icon><Plus /></el-icon> 添加航段
</el-button>
</div>
</template>
<div v-for="(seg, idx) in form.routeSegments" :key="idx" class="segment-row">
<el-row :gutter="12">
<el-col :span="3">
<el-input v-model="seg.fromPortCode" placeholder="起点" size="small" />
</el-col>
<el-col :span="3">
<el-input v-model="seg.toPortCode" placeholder="终点" size="small" />
</el-col>
<el-col :span="3">
<el-input-number v-model="seg.distanceNauticalMiles" :min="0" size="small" />
</el-col>
<!-- 更多字段... -->
<el-col :span="1">
<el-button type="danger" size="small" link @click="removeSegment(idx)">
<el-icon><Delete /></el-icon>
</el-button>
</el-col>
</el-row>
</div>
</el-card>
3.6 编辑页(PlanEdit.vue)
我的 Prompt:
请实现航次计划编辑页,与创建页类似但有以下区别:
1. 进入页面时加载已有数据,填充表单
2. 航次编号不可修改(disabled)
3. 增加"修改人"字段
4. 提交调用 update API
5. 返回按钮跳转到详情页(而非列表页)
四、路由配置
我的 Prompt:
请配置 Vue Router,包含以下路由:
/ → PlanList(列表页)
/detail/:id → PlanDetail(详情页)
/create → PlanCreate(创建页)
/edit/:id → PlanEdit(编辑页)
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import PlanList from '../views/PlanList.vue'
import PlanDetail from '../views/PlanDetail.vue'
import PlanCreate from '../views/PlanCreate.vue'
import PlanEdit from '../views/PlanEdit.vue'
const routes = [
{ path: '/', component: PlanList },
{ path: '/detail/:id', component: PlanDetail },
{ path: '/create', component: PlanCreate },
{ path: '/edit/:id', component: PlanEdit },
]
export default createRouter({
history: createWebHistory(),
routes
})
五、前后端联调
5.1 启动服务
# 终端 1:启动后端
cd src/VoyagePlan.Api && dotnet run
# 终端 2:启动前端
cd frontend && npm install && npm run dev
5.2 联调验证
- 打开
http://localhost:3000,看到列表页 - 点击「新建计划」,填写表单,提交
- 创建成功后跳转到详情页,确认数据正确
- 返回列表页,确认新计划已显示
- 测试状态流转:发布 → 变更 → 完成变更 → 取消
5.3 常见问题
问题:跨域请求失败
我的 Prompt:
前端请求后端报 CORS 错误:
Access to XMLHttpRequest at 'http://localhost:5000/api/...'
from origin 'http://localhost:3000' has been blocked by CORS policy
如何解决?
DeepSeek 的解答:
在 Program.cs 中配置 CORS:
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowFrontend", policy =>
{
policy.WithOrigins("http://localhost:3000")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
// ...
app.UseCors("AllowFrontend");
或者使用 Vite 代理(推荐开发环境):
// vite.config.js
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true
}
}
六、Prompt 技巧总结
1. 描述页面布局时用视觉语言
❌ "做一个列表页"
✅ "做一个列表页,顶部有状态筛选和新建按钮,
中间是 el-table 表格,操作列在右侧固定,
不同状态用不同颜色的 Tag 显示"
2. 指定组件和交互方式
❌ "实现表单提交"
✅ "使用 el-form + el-form-item 实现表单,
必填字段加 rules 校验,
提交前调用 validate(),
成功后用 ElMessage.success 提示并跳转"
3. 让 AI 处理边界情况
请处理以下边界情况:
1. 列表为空时显示空状态
2. 加载数据时显示 loading
3. 请求失败时显示错误提示
4. 删除/取消操作需要二次确认
七、系列总结
通过 5 篇博客,我们完整演示了如何用 DeepSeek 辅助完成一个航运业务系统的全栈开发:
| 阶段 | 工具 | 产出 |
|---|---|---|
| 需求调研 | DeepSeek 对话 | PRD 文档、功能列表 |
| 软件设计 | DeepSeek 对话 | 架构图、领域模型、API 设计 |
| 领域编码 | DeepSeek 生成代码 | DDD 四层架构后端代码 |
| 后端测试 | DeepSeek 生成测试 | 6 个单元测试 + 联调 |
| 前端开发 | DeepSeek 生成代码 | Vue 3 + Element Plus 4 个页面 |
核心心得:
- AI 是加速器,不是替代品:DeepSeek 帮你快速生成 80% 的代码,但剩余 20% 的审查、调试和业务适配需要人工完成
- Prompt 质量决定输出质量:越具体的 Prompt(包含技术栈、组件名、交互方式),输出越接近可用
- 分步迭代优于一步到位:按层/按模块逐步生成,每步验证后再进行下一步
- 让 AI 处理重复性工作:CRUD 代码、表单校验、测试用例这些重复性工作,AI 比人更高效
希望这个系列能帮助你在实际项目中更好地利用 DeepSeek 提升开发效率。
更多推荐

所有评论(0)