实现多角色模式切换

新增功能 支持 4 种模式:

  • 默认助手
  • 技术顾问
  • 面试教练
  • 陪伴模式

效果:

  • 已有会话可切换新建会话时可指定角色角色
  • 切换后自动更新该会话的 system prompt
  • 左侧列表可看到当前角色标签

1)新增文件

web/src/utils/persona.js

css 复制代码
export const PERSONA_MAP = {
  default: {
    label: '默认助手',
    systemPrompt: '你是一个专业、友好、清晰的 AI 助手,回答准确,表达简洁。',
  },
  tech: {
    label: '技术顾问',
    systemPrompt:
      '你是一个资深技术顾问,擅长前端、后端、AI Agent、工程架构。回答要结构化、专业、可落地,优先给出实操建议。',
  },
  interview: {
    label: '面试教练',
    systemPrompt:
      '你是一个资深面试教练,擅长帮助候选人准备前端、全栈、AI Agent、系统设计面试。回答要突出面试重点、考点、答题思路和表达方式。',
  },
  companion: {
    label: '陪伴模式',
    systemPrompt:
      '你是一个温柔、聪明、会长期陪伴用户的 AI 伙伴。你会共情、鼓励、倾听,并自然结合上下文进行交流。',
  },
}

export const PERSONA_OPTIONS = Object.entries(PERSONA_MAP).map(([value, item]) => ({
  value,
  label: item.label,
}))

2)改 web/src/utils/session.js

javascript 复制代码
import { PERSONA_MAP } from './persona'

createSession 改成:

javascript 复制代码
export function createSession(title = '新对话', mode = 'companion') {
  const persona = PERSONA_MAP[mode] || PERSONA_MAP.companion

  return {
    id: crypto.randomUUID(),
    title,
    mode,
    pinned: false,
    createdAt: Date.now(),
    updatedAt: Date.now(),
    messages: [
      {
        role: 'system',
        content: persona.systemPrompt,
      },
      {
        role: 'assistant',
        content: '你好,我已经准备好了。你今天想聊什么?',
      },
    ],
  }
}

loadSessions 里的 normalize 部分

php 复制代码
    const normalized = sessions.map(item => ({
      mode: 'companion',
      pinned: false,
      ...item,
    }))

3)改 web/src/App.vue

改 import

javascript 复制代码
import { createSession, loadSessions, saveSessions, sortSessions } from './utils/session'
import { PERSONA_MAP, PERSONA_OPTIONS } from './utils/persona'

新增状态

csharp 复制代码
const createMode = ref('companion')

新增方法

ini 复制代码
const resetSystemMessageByMode = (messages = [], mode = 'companion') => {
  const persona = PERSONA_MAP[mode] || PERSONA_MAP.companion
  const nextMessages = [...messages]

  const systemIndex = nextMessages.findIndex(item => item.role === 'system')
  if (systemIndex > -1) {
    nextMessages[systemIndex] = {
      ...nextMessages[systemIndex],
      content: persona.systemPrompt,
    }
  } else {
    nextMessages.unshift({
      role: 'system',
      content: persona.systemPrompt,
    })
  }

  return nextMessages
}

const handleChangeSessionMode = (id, mode) => {
  sessions.value = sortSessions(
    sessions.value.map(item =>
      item.id === id
        ? {
            ...item,
            mode,
            updatedAt: Date.now(),
            messages: resetSystemMessageByMode(item.messages, mode),
          }
        : item
    )
  )
}

handleCreateSession

ini 复制代码
const handleCreateSession = () => {
  const session = createSession(`新对话 ${sessions.value.length + 1}`, createMode.value)
  sessions.value = sortSessions([session, ...sessions.value])
  currentSessionId.value = session.id
}

4)改模板

在左侧新建按钮下面加角色选择

ini 复制代码
<select v-model="createMode" class="mode-select">
  <option
    v-for="item in PERSONA_OPTIONS"
    :key="item.value"
    :value="item.value"
  >
    {{ item.label }}
  </option>
</select>

在每个会话卡片里加角色标签和切换

ini 复制代码
<div class="session-meta">
  <span class="mode-badge">
    {{ PERSONA_MAP[item.mode]?.label || '陪伴模式' }}
  </span>

  <select
    class="session-mode-select"
    :value="item.mode"
    @click.stop
    @change.stop="handleChangeSessionMode(item.id, $event.target.value)"
  >
    <option
      v-for="option in PERSONA_OPTIONS"
      :key="option.value"
      :value="option.value"
    >
      {{ option.label }}
    </option>
  </select>
</div>

<div class="session-time">{{ formatTime(item.updatedAt) }}</div>

5)补充样式

css 复制代码
.mode-select {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid #d1d5db;
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 14px;
  outline: none;
  margin-bottom: 12px;
  background: #fff;
}

.session-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}

.mode-badge {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  line-height: 1;
  padding: 5px 8px;
  border-radius: 999px;
  background: #ecfeff;
  color: #0f766e;
}

.session-mode-select {
  max-width: 110px;
  border: 1px solid #d1d5db;
  border-radius: 8px;
  padding: 4px 6px;
  font-size: 12px;
  background: #fff;
  color: #374151;
  outline: none;
}

6)验证

新建会话时选模式

先切换成:

  • 技术顾问
  • 面试教练
  • 陪伴模式

再点新建,会话会带着对应系统人设创建。

已有会话切模式

在某个会话卡片里切换角色后,再提问:

不同模式的回答风格不同。

非常nice !

仓库地址

完整代码请看仓库,仓库地址:github.com/huanhunmao/... star 🌟🌟🌟 谢谢~

相关推荐
|晴 天|3 小时前
Vue 3 + TypeScript + Element Plus 博客系统开发总结与思考
前端·vue.js·typescript
Agent手记4 小时前
制造业数字化升级:生产全流程企业级智能体落地解决方案 —— 基于LLM+超自动化全栈架构的智改数转深度实战
运维·ai·架构·自动化
猫3284 小时前
v-cloak
前端·javascript·vue.js
旷世奇才李先生4 小时前
Vue 3\+Vite\+Pinia实战:企业级前端项目架构设计
前端·javascript·vue.js
旷世奇才李先生6 小时前
Spring Cloud Alibaba 2026实战:微服务治理全解析
微服务·云原生·架构
SoaringHeart6 小时前
Flutter进阶:用OverlayEntry 实现所有弹窗效果
前端·flutter
heimeiyingwang7 小时前
【架构实战】混合云架构设计方案
架构
IT_陈寒8 小时前
Vite静态资源加载把我坑惨了
前端·人工智能·后端
herinspace8 小时前
管家婆实用贴-如何分离和附加数据库
开发语言·前端·javascript·数据库·语音识别
小码哥_常8 小时前
从MVC到MVI:一文吃透架构模式进化史
前端