` | ❌ 缺少 `draggable="true"` 属性,即使改用 `dragstart` 事件也无法触发拖拽 |
**核心问题链**:
1. `mousedown` 事件没有 `dataTransfer` → `dt` 为 `undefined`
2. `if (vueFlowRef.value && dt)` 条件永远为 `false`
3. `dt.setData('application/vueflow', ...)` 永远不执行
4. `onDrop` 中 `event.dataTransfer?.getData('application/vueflow')` 返回 `null`
5. 函数直接 `return`,不创建任何节点
**为什么"没有任何报错"**: 因为代码流程中每个 `if` 条件都静默返回了 `null/undefined`,没有走到会抛异常的逻辑路径。
#### 解决方案
**修改文件**: `frontend/src/views/flow/FlowEditor.vue`
**修改点1** — 模板: 将 `@mousedown` 改为 `@dragstart`,添加 `draggable="true"`
第21-29行,改为:
```html
```
**修改点2** — 脚本: 修复 `onDragStart` 函数
第253-259行,改为:
```typescript
function onDragStart(event: DragEvent, node: (typeof nodeTypes)[0]) {
if (event.dataTransfer) {
event.dataTransfer.setData('application/vueflow', JSON.stringify(node))
event.dataTransfer.effectAllowed = 'move'
}
}
```
**修改点3** — 脚本: 增强 `onDrop` 函数的健壮性
第261-291行,改为:
```typescript
function onDrop(event: DragEvent) {
const dataStr = event.dataTransfer?.getData('application/vueflow')
if (!dataStr) return
const nodeData = JSON.parse(dataStr)
// 使用 Vue Flow 内置方法计算画布坐标,回退到手动估算
let position = { x: 100, y: 100 }
try {
const bounds = (event.currentTarget as HTMLElement)?.getBoundingClientRect()
if (bounds) {
position = {
x: event.clientX - bounds.left - 80,
y: event.clientY - bounds.top - 20,
}
}
} catch { /* fallback to default position */ }
const id = `node_${nodeCounter++}`
const newNode: any = {
id,
type: 'custom',
position,
data: {
label: nodeData.label,
type: nodeData.type,
typeDesc: nodeData.typeDesc,
color: colorMap[nodeData.type] || '#409EFF',
config: nodeData.type === 'llm'
? { system_prompt: '', model: 'gpt-4o-mini', temperature: 0.7 }
: {},
},
draggable: true,
connectable: true,
}
elements.value = [...elements.value, newNode]
}
```
---
### 问题3: 流详情 `/api/flow/definitions/:id` 直接在菜单中出现,未传ID导致422错误
#### 根因分析
**问题源**: `frontend/src/components/layout/AdminLayout.vue` 第46行:
```html
流详情
```
这段代码存在两个严重问题:
1. **`:id` 是路由参数占位符,不能直接作为菜单导航路径**:
- 点击菜单 → `router.push('/admin/flow/market/:id')`
- 前端路由匹配路径 `/admin/flow/market/:id` → `route.params.id` = `':id'` (字面量)
- 组件 `FlowDetail.vue` 调用 API `flowApi.getFlow(':id')`
- 发送请求 `GET /api/flow/definitions/%3Aid` → 422 Unprocessable Entity
2. **业务逻辑错误**: 流详情是**列表项的操作入口**(点击某条流记录 → 查看详情),而不是一个独立的导航菜单项。用户必须先选择一个具体的流,才能查看其详情。
**对比已有的正确设计**:
- `TaskDetail` 路由: `/user/task/:id` — **不在菜单中**,只能通过任务列表点击跳转
- `FlowEditor` 编辑路由: `/admin/flow/editor/:id` — **不在菜单中**,通过流列表点击跳转
- `FlowDetail` 流详情路由: `/admin/flow/market/:id` — **错误地放在菜单中**
#### 解决方案
**修改文件1**: `frontend/src/components/layout/AdminLayout.vue`
删除第46行:
```diff
-
流详情
```
同时检查 `FlowList.vue` 和 `FlowMarket.vue` 是否已有正确的详情跳转入口(Card点击 → `router.push('/admin/flow/market/:id')`),如果没有则需要补充。
**修改文件2**: `frontend/src/views/flow/FlowList.vue` — 确保每条流记录点击能跳转到详情
检查并确保 FlowList 每行有跳转逻辑:
```typescript
function viewFlow(id: string) {
router.push(`/admin/flow/market/${id}`)
}
```
---
### 问题4: 管理后台和企业AI后台 —— 做成固定在右上角账号隔壁的选择项
#### 根因分析
**当前实现位置**:
- `MainLayout.vue` 第72-75行: "管理后台" 入口放在 **左侧边栏底部**(仅管理员可见)
- `AdminLayout.vue` 第86-89行: "返回用户端" 入口放在 **左侧边栏底部**
**存在的问题**:
1. 入口位置隐蔽,用户不易发现
2. "管理后台"入口被混在功能菜单中,不够突出
3. 两个入口位于不同布局,缺少统一的切换组件
4. 没有明确的视觉状态指示当前所在端
**需求**: 做成固定在右上角、账号头像旁边的**明确可切换的选择项**
#### 解决方案
**方案**: 在两个 Layout 的 `header-right` 区域统一添加"端切换"组件
##### 4.1 创建公共切换组件
文件: `frontend/src/components/common/PortalSwitcher.vue`
```vue
企业AI
管理后台
```
##### 4.2 修改 MainLayout.vue
第88-102行区域的 `header-right`,在用户下拉菜单前插入 PortalSwitcher:
```diff
```
同时**移除**第72-75行的侧边栏管理后台入口:
```diff
-
-
- 管理后台
-
```
##### 4.3 修改 AdminLayout.vue
同样在 header-right 区域插入 PortalSwitcher:
```diff
```
同时**移除**第86-89行的侧边栏返回用户端入口:
```diff
-
-
- 返回用户端
-
```
---
## 三、P3 级体验优化(下期规划)
> 来源: PLAN2.md "六、剩余可优化项"
### 3.1 全局搜索
| 项目 | 详情 |
|------|------|
| **入口位置** | 顶部导航栏中央,全局搜索框(Cmd/Ctrl + K 快捷键唤起) |
| **搜索范围** | 任务名称/ID、流名称/ID、员工姓名、部门名称、智能体类型 |
| **交互设计** | 输入关键词 → 实时下拉联想 → 选中 → 跳转到对应详情页 |
| **技术方案** | 前端: `el-autocomplete` + 防抖;后端: 新增 `GET /api/search?q=keyword` 聚合搜索接口 |
| **前端文件** | 新增 `components/common/GlobalSearch.vue` |
| **后端文件** | 新增 `modules/search/router.py` |
### 3.2 主题切换(深色/浅色模式)
| 项目 | 详情 |
|------|------|
| **入口位置** | 右上角 PortalSwitcher 旁边,添加主题切换按钮(太阳/月亮图标) |
| **切换内容** | Element Plus CSS 变量覆盖 + 自定义页面背景色 |
| **持久化** | localStorage 存 `theme` 字段,刷新后保持 |
| **技术方案** | 使用 `el-config-provider` 的 `namespace` + CSS 变量覆盖。Element Plus 2.x 原生支持暗黑模式(添加 `dark` class 到 `html` 元素) |
| **前端文件** | 新增 `stores/theme.ts` + 修改 `main.ts` |
| **CSS文件** | 新增 `styles/dark.css` |
### 3.3 国际化(i18n 多语言)
| 项目 | 详情 |
|------|------|
| **支持语言** | 简体中文(zh-CN)、英文(en-US) |
| **实现方案** | vue-i18n ^9.x,语言包按模块拆分 |
| **入口位置** | 右上角 PortalSwitcher 旁边,语言切换下拉或图标 |
| **持久化** | localStorage 存 `locale` 字段 |
| **翻译范围** | 菜单、按钮、表单标签、提示信息、表格列头、错误信息 |
| **前端文件** | 新增 `locales/zh-CN.ts`、`locales/en-US.ts`、`locales/index.ts` |
### 3.4 新手引导(首次登录操作指引)
| 项目 | 详情 |
|------|------|
| **触发条件** | 用户表中 `onboarding_completed` 字段为 false |
| **引导步骤** | ① 欢迎 → ② 查看工作台 → ③ 创建任务 → ④ 查看智能体 → ⑤ 进入管理后台(仅管理员) |
| **实现方案** | driver.js 或 intro.js 库,高亮目标元素 + 文字提示泡泡 |
| **跳过机制** | 引导面板有"跳过"和"不再显示"按钮 |
| **前端文件** | 新增 `components/common/OnboardingGuide.vue` |
| **后端文件** | `PUT /api/auth/me` 增加 `onboarding_completed` 字段支持 |
### 3.5 移动端适配(响应式布局)
| 项目 | 详情 |
|------|------|
| **适配范围** | 工作台、任务列表、智能体对话、通知中心(核心用户端功能) |
| **布局策略** | 768px 以下: 侧边栏隐藏(汉堡菜单),内容区全宽,表格横向滚动 |
| **组件调整** | el-card → 边距缩小,el-table → 固定列+横向滚动,el-form → 标签在上 |
| **CSS方案** | 全局 `@media (max-width: 768px)` + Element Plus 响应式断点 |
| **管理后台** | 仅做基本适配(可左右滚动),不做深度移动端优化 |
| **前端文件** | 新增 `styles/mobile.css` + 各页面添加响应式 scoped style |
---
## 四、实施优先级与排期
### 4.1 本期(P0 紧急修复)
| # | 任务 | 文件 | 工作量 |
|---|------|------|--------|
| 1 | 修复企微配置500错误(缺少settings导入) | `backend/modules/wecom/router.py` | 5分钟 |
| 2 | 修复节点拖拽(mousedown→dragstart + draggable) | `frontend/src/views/flow/FlowEditor.vue` | 15分钟 |
| 3 | 移除菜单中的"流详情"(`:id`占位符) | `frontend/src/components/layout/AdminLayout.vue` | 5分钟 |
| 4 | PortalSwitcher 创建并集成到两个Layout | `frontend/src/components/common/PortalSwitcher.vue` + `MainLayout.vue` + `AdminLayout.vue` | 30分钟 |
| 5 | 过滤 Chrome 扩展 runtime.lastError | `frontend/src/main.ts` 或 `index.html` | 5分钟 |
### 4.2 下期(P3 体验优化)
| # | 任务 | 工作量 | 建议排期 |
|---|------|--------|---------|
| 6 | 全局搜索 | 2天 | Week 1 |
| 7 | 主题切换(深色/浅色) | 1天 | Week 1 |
| 8 | 国际化 i18n | 2天 | Week 2 |
| 9 | 新手引导 | 1天 | Week 2 |
| 10 | 移动端适配 | 2天 | Week 2-3 |
---
## 五、验证检查清单
实施完成后,使用 **sroot** 账号验证:
```
□ 企微配置页面正常加载(不再500报错)
□ 节点面板拖拽到画布: 拖拽正常 → 节点出现在画布上
□ 菜单中不再出现"流详情"菜单项
□ 从流列表/流市场点击具体流 → 正确跳转流详情
□ 右上角显示 PortalSwitcher 切换按钮
□ 在企业AI端 → 点击"管理后台" → 切换到管理后台
□ 在管理后台 → 点击"企业AI" → 切换回企业AI端
□ 流编辑器页面加载无 Chrome runtime.lastError 警告
```