feat:rename subtree from frontend-vue to frontend
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
<script setup lang="ts">
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { pick } from 'lodash'
|
||||
|
||||
import api from '@/api/index.ts'
|
||||
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { agentMapDuty } from '@/layout/components/config.ts'
|
||||
import { type Agent, useAgentsStore } from '@/stores'
|
||||
import { onMounted } from 'vue'
|
||||
import { readConfig } from '@/utils/readJson.ts'
|
||||
import AgentRepoList from './AgentRepoList.vue'
|
||||
|
||||
const agentsStore = useAgentsStore()
|
||||
|
||||
// 如果agentsStore.agents不存在就读取默认配置的json文件
|
||||
onMounted(async () => {
|
||||
if (!agentsStore.agents.length) {
|
||||
const res = await readConfig<Agent[]>('agent.json')
|
||||
agentsStore.setAgents(res)
|
||||
}
|
||||
await api.setAgents(agentsStore.agents.map((item) => pick(item, ['Name', 'Profile'])))
|
||||
})
|
||||
|
||||
// 上传agent文件
|
||||
const fileInput = ref<HTMLInputElement>()
|
||||
|
||||
const triggerFileSelect = () => {
|
||||
fileInput.value?.click()
|
||||
}
|
||||
|
||||
const handleFileSelect = (event: Event) => {
|
||||
const input = event.target as HTMLInputElement
|
||||
if (input.files && input.files[0]) {
|
||||
const file = input.files[0]
|
||||
readFileContent(file)
|
||||
}
|
||||
}
|
||||
|
||||
const readFileContent = async (file: File) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = async (e) => {
|
||||
if (!e.target?.result) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const json = JSON.parse(e.target.result?.toString?.() ?? '{}')
|
||||
// 处理 JSON 数据
|
||||
if (Array.isArray(json)) {
|
||||
const isValid = json.every(
|
||||
(item) =>
|
||||
typeof item.Name === 'string' &&
|
||||
typeof item.Icon === 'string' &&
|
||||
typeof item.Profile === 'string',
|
||||
)
|
||||
if (isValid) {
|
||||
// 处理有效的 JSON 数据
|
||||
agentsStore.setAgents(
|
||||
json.map((item) => ({
|
||||
Name: item.Name,
|
||||
Icon: item.Icon.replace(/\.png$/, ''),
|
||||
Profile: item.Profile,
|
||||
Classification: item.Classification,
|
||||
})),
|
||||
)
|
||||
await api.setAgents(json.map((item) => pick(item, ['Name', 'Profile'])))
|
||||
} else {
|
||||
ElNotification.error({
|
||||
title: '错误',
|
||||
message: 'JSON 格式错误',
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.error('JSON is not an array')
|
||||
ElNotification.error({
|
||||
title: '错误',
|
||||
message: 'JSON 格式错误',
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
reader.readAsText(file)
|
||||
}
|
||||
|
||||
// 根据currentTask排序agent列表
|
||||
const agentList = computed(() => {
|
||||
const selected: Agent[] = []
|
||||
const unselected: {
|
||||
title: string
|
||||
data: Agent[]
|
||||
}[] = []
|
||||
const obj: Record<string, Agent[]> = {}
|
||||
if (!agentsStore.agents.length) {
|
||||
return {
|
||||
selected,
|
||||
unselected,
|
||||
}
|
||||
}
|
||||
for (const agent of agentsStore.agents) {
|
||||
// if (agentsStore.currentTask?.AgentSelection?.includes(agent.Name)) {
|
||||
// selected.push(agent)
|
||||
// continue
|
||||
// }
|
||||
if (obj[agent.Classification]) {
|
||||
obj[agent.Classification]!.push(agent)
|
||||
} else {
|
||||
const arr = [agent]
|
||||
obj[agent.Classification] = arr
|
||||
unselected.push({
|
||||
title: agent.Classification,
|
||||
data: arr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
selected,
|
||||
unselected: unselected,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="agent-repo h-full flex flex-col" id="agent-repo">
|
||||
<!-- 头部 -->
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-[18px] font-bold">智能体库</span>
|
||||
<!-- 上传文件 -->
|
||||
<input type="file" accept=".json" @change="handleFileSelect" class="hidden" ref="fileInput" />
|
||||
<div class="plus-button" @click="triggerFileSelect">
|
||||
<svg-icon icon-class="plus" color="var(--color-text)" size="18px" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 智能体列表 -->
|
||||
<div class="pt-[18px] flex-1 overflow-y-auto relative">
|
||||
<!-- 已选中的智能体 -->
|
||||
<AgentRepoList :agent-list="agentList.selected" />
|
||||
<!-- 为选择的智能体 -->
|
||||
<div v-for="agent in agentList.unselected" :key="agent.title">
|
||||
<p class="text-[12px] font-bold py-[8px]">{{ agent.title }}</p>
|
||||
<AgentRepoList :agent-list="agent.data" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部提示栏 -->
|
||||
<div class="w-full grid grid-cols-3 gap-x-[10px] bg-[#1d222b] rounded-[20px] p-[8px] mt-[10px]">
|
||||
<div
|
||||
v-for="item in Object.values(agentMapDuty)"
|
||||
:key="item.key"
|
||||
class="flex items-center justify-center gap-x-1"
|
||||
>
|
||||
<span class="text-[12px]">{{ item.name }}</span>
|
||||
<div class="w-[8px] h-[8px] rounded-full" :style="{ background: item.color }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.agent-repo {
|
||||
padding: 0 8px;
|
||||
|
||||
.plus-button {
|
||||
background: #1d2128;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: #374151;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#agent-repo {
|
||||
:deep(.agent-repo-item-popover) {
|
||||
padding: 0;
|
||||
border-radius: 20px;
|
||||
background: var(--color-bg-secondary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user