358 lines
9.8 KiB
Vue
358 lines
9.8 KiB
Vue
<!--
|
||||
|
|
Copyright 2024-2026 ReplyPier
|
|||
|
|
|
|||
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|||
|
|
you may not use this file except in compliance with the License.
|
|||
|
|
You may obtain a copy of the License at
|
|||
|
|
|
|||
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|
|
|||
|
|
Unless required by applicable law or agreed to in writing, software
|
|||
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|||
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
|
|
See the License for the specific language governing permissions and
|
|||
|
|
limitations under the License.
|
|||
|
|
-->
|
|||
|
|
|
|||
|
|
<script setup lang="ts">
|
|||
|
|
import type { Agent } from '@/types/agent'
|
|||
|
|
import { useAgentCreate } from '@/composables/useAgentCreate'
|
|||
|
|
|
|||
|
|
const {
|
|||
|
|
agentName,
|
|||
|
|
useWorkflow,
|
|||
|
|
isCreating,
|
|||
|
|
error,
|
|||
|
|
createAgent
|
|||
|
|
} = useAgentCreate()
|
|||
|
|
|
|||
|
|
const emit = defineEmits<{
|
|||
|
|
(e: 'close'): void
|
|||
|
|
(e: 'created', agent: Agent): void
|
|||
|
|
(e: 'openWorkflowBuilder', agent: Agent): void
|
|||
|
|
}>()
|
|||
|
|
|
|||
|
|
const handleCreateAgent = async () => {
|
|||
|
|
const newAgent = await createAgent()
|
|||
|
|
if (newAgent) {
|
|||
|
|
emit('created', newAgent)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<div class="modal-overlay">
|
|||
|
|
<div class="modal-content" role="dialog" aria-modal="true" aria-labelledby="create-agent-title">
|
|||
|
|
<div class="modal-header">
|
|||
|
|
<h3 id="create-agent-title">创建客服</h3>
|
|||
|
|
<button type="button" class="close-button" aria-label="关闭" @click="$emit('close')">×</button>
|
|||
|
|
</div>
|
|||
|
|
<div class="modal-body">
|
|||
|
|
<form @submit.prevent="handleCreateAgent">
|
|||
|
|
<div class="form-group">
|
|||
|
|
<label for="agent-name">客服名称</label>
|
|||
|
|
<input
|
|||
|
|
id="agent-name"
|
|||
|
|
type="text"
|
|||
|
|
v-model="agentName"
|
|||
|
|
placeholder="例如:客户支持客服"
|
|||
|
|
:disabled="isCreating"
|
|||
|
|
required
|
|||
|
|
>
|
|||
|
|
<div class="help-text">
|
|||
|
|
为客服起个名字,访客会看到这个名称。
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-group mode-selection">
|
|||
|
|
<label>客服模式</label>
|
|||
|
|
<div class="mode-options">
|
|||
|
|
<div
|
|||
|
|
class="mode-option"
|
|||
|
|
:class="{ 'selected': !useWorkflow }"
|
|||
|
|
@click="useWorkflow = false"
|
|||
|
|
>
|
|||
|
|
<div class="mode-icon">
|
|||
|
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
|
<path d="M12 3l1.9 4.6L18.5 9l-4.6 1.4L12 15l-1.9-4.6L5.5 9l4.6-1.4z"/>
|
|||
|
|
<path d="M19 14l.7 1.8L21.5 16.5l-1.8.7L19 19l-.7-1.8L16.5 16.5l1.8-.7z"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
<div class="mode-details">
|
|||
|
|
<h4>AI 自动模式</h4>
|
|||
|
|
<p>让 AI 依据指令自然应答</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div
|
|||
|
|
class="mode-option"
|
|||
|
|
:class="{ 'selected': useWorkflow }"
|
|||
|
|
@click="useWorkflow = true"
|
|||
|
|
>
|
|||
|
|
<div class="mode-icon">
|
|||
|
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
|
<circle cx="6" cy="6" r="2.4"/>
|
|||
|
|
<circle cx="6" cy="18" r="2.4"/>
|
|||
|
|
<circle cx="18" cy="9" r="2.4"/>
|
|||
|
|
<path d="M8.4 6H13a3 3 0 0 1 3 3M6 8.4v7.2"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
<div class="mode-details">
|
|||
|
|
<h4>工作流编排</h4>
|
|||
|
|
<p>拖拽搭建自定义对话流程</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div v-if="error" class="error-message">
|
|||
|
|
{{ error }}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="form-actions">
|
|||
|
|
<button
|
|||
|
|
type="button"
|
|||
|
|
class="cancel-button"
|
|||
|
|
@click="$emit('close')"
|
|||
|
|
:disabled="isCreating"
|
|||
|
|
>
|
|||
|
|
取消
|
|||
|
|
</button>
|
|||
|
|
<button
|
|||
|
|
type="submit"
|
|||
|
|
class="create-button"
|
|||
|
|
:disabled="isCreating"
|
|||
|
|
>
|
|||
|
|
{{ isCreating ? '创建中…' : '创建客服' }}
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.modal-overlay {
|
|||
|
|
position: fixed;
|
|||
|
|
top: 0;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
bottom: 0;
|
|||
|
|
background-color: rgba(255, 255, 255, 0.5);
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
z-index: 1000;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.modal-content {
|
|||
|
|
background: var(--surface);
|
|||
|
|
border: 1px solid var(--o10);
|
|||
|
|
border-radius: 24px;
|
|||
|
|
width: 90%;
|
|||
|
|
max-width: 600px;
|
|||
|
|
max-height: 90vh;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
box-shadow: 0 12px 48px rgba(0, 0, 0, 0.2);
|
|||
|
|
animation: modal-appear 0.3s ease-out;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@keyframes modal-appear {
|
|||
|
|
from {
|
|||
|
|
opacity: 0;
|
|||
|
|
transform: translateY(20px);
|
|||
|
|
}
|
|||
|
|
to {
|
|||
|
|
opacity: 1;
|
|||
|
|
transform: translateY(0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.modal-header {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
padding: var(--space-lg) var(--space-lg) var(--space-md);
|
|||
|
|
border-bottom: 1px solid var(--border-color);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.modal-header h3 {
|
|||
|
|
margin: 0;
|
|||
|
|
font-size: 1.5rem;
|
|||
|
|
color: var(--text-color);
|
|||
|
|
font-weight: 600;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.close-button {
|
|||
|
|
background: none;
|
|||
|
|
border: none;
|
|||
|
|
font-size: 1.5rem;
|
|||
|
|
cursor: pointer;
|
|||
|
|
color: var(--text-muted);
|
|||
|
|
line-height: 1;
|
|||
|
|
padding: 0;
|
|||
|
|
margin: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.close-button:hover {
|
|||
|
|
color: var(--text-color);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.modal-body {
|
|||
|
|
padding: var(--space-lg);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.form-group {
|
|||
|
|
margin-bottom: var(--space-lg);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
label {
|
|||
|
|
display: block;
|
|||
|
|
margin-bottom: var(--space-xs);
|
|||
|
|
font-weight: 500;
|
|||
|
|
color: var(--text-color);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
input {
|
|||
|
|
width: 100%;
|
|||
|
|
padding: var(--space-md);
|
|||
|
|
border: 1px solid var(--border-color);
|
|||
|
|
border-radius: var(--radius-md);
|
|||
|
|
background: var(--background-soft);
|
|||
|
|
color: var(--text-color);
|
|||
|
|
font-size: 1rem;
|
|||
|
|
transition: border-color 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
input:focus {
|
|||
|
|
outline: none;
|
|||
|
|
border-color: var(--primary-color);
|
|||
|
|
box-shadow: 0 0 0 2px var(--primary-soft);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.help-text {
|
|||
|
|
font-size: 0.875rem;
|
|||
|
|
color: var(--text-muted);
|
|||
|
|
margin-top: var(--space-xs);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.error-message {
|
|||
|
|
background-color: var(--error-soft);
|
|||
|
|
color: var(--error-color);
|
|||
|
|
padding: var(--space-md);
|
|||
|
|
border-radius: var(--radius-md);
|
|||
|
|
margin-bottom: var(--space-lg);
|
|||
|
|
font-size: 0.875rem;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-options {
|
|||
|
|
display: flex;
|
|||
|
|
gap: var(--space-md);
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-option {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: var(--space-md);
|
|||
|
|
padding: var(--space-md);
|
|||
|
|
border: 2px solid var(--border-color);
|
|||
|
|
border-radius: var(--radius-lg);
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-option.selected {
|
|||
|
|
border-color: var(--primary-color);
|
|||
|
|
background-color: var(--primary-soft);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-icon {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
width: 44px;
|
|||
|
|
height: 44px;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
border-radius: var(--radius-md);
|
|||
|
|
background: var(--o05);
|
|||
|
|
border: 1px solid var(--o10);
|
|||
|
|
color: var(--muted);
|
|||
|
|
transition: all 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-option.selected .mode-icon {
|
|||
|
|
background: var(--accent-bg-08);
|
|||
|
|
border-color: var(--accent-border);
|
|||
|
|
color: var(--accent-ink);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-details {
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-details h4 {
|
|||
|
|
margin: 0 0 var(--space-xs);
|
|||
|
|
font-size: 1.1rem;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-details p {
|
|||
|
|
margin: 0;
|
|||
|
|
color: var(--text-muted);
|
|||
|
|
font-size: 0.875rem;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.form-actions {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: flex-end;
|
|||
|
|
gap: var(--space-md);
|
|||
|
|
margin-top: var(--space-xl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.cancel-button {
|
|||
|
|
padding: var(--space-md) var(--space-lg);
|
|||
|
|
border: 1px solid var(--border-color);
|
|||
|
|
border-radius: var(--radius-md);
|
|||
|
|
background: var(--background-soft);
|
|||
|
|
color: var(--text-color);
|
|||
|
|
font-weight: 500;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.cancel-button:hover {
|
|||
|
|
background: var(--background-muted);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.create-button {
|
|||
|
|
padding: var(--space-md) var(--space-lg);
|
|||
|
|
border: none;
|
|||
|
|
border-radius: var(--radius-md);
|
|||
|
|
background: var(--accent-solid);
|
|||
|
|
color: var(--on-accent-solid);
|
|||
|
|
font-weight: 500;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.create-button:hover {
|
|||
|
|
background: var(--primary-dark);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.create-button:disabled,
|
|||
|
|
.cancel-button:disabled {
|
|||
|
|
opacity: 0.6;
|
|||
|
|
cursor: not-allowed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@media (min-width: 768px) {
|
|||
|
|
.mode-options {
|
|||
|
|
flex-direction: row;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mode-option {
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|