feat(config): 添加配置文件支持动态标题和提示词
- 新增 public/config.json 配置文件,包含网站标题、副标题及任务提示词 - 在 Header 组件中读取并应用配置中的标题信息-为 Task 组件的搜索建议框引入配置中的提示词列表 - 创建 useConfigStore 管理全局配置状态,并在应用初始化时加载配置 - 更新 main.ts 在应用启动时设置文档标题 - 移除了 Task.vue 中硬编码的提示词数组,改由配置驱动-修复了 agents store 中版本标识监听逻辑,实现存储清理功能 - 添加 MultiLineTooltip 组件用于文本溢出时显示完整内容 -重构 TaskSyllabus 页面布局与样式,提升视觉效果与交互体验 - 引入 Bg
This commit is contained in:
parent
00ef22505e
commit
041986f5cd
1
components.d.ts
vendored
1
components.d.ts
vendored
@ -18,6 +18,7 @@ declare module 'vue' {
|
||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||
MultiLineTooltip: typeof import('./src/components/MultiLineTooltip/index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
|
||||
|
||||
19
public/config.json
Normal file
19
public/config.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"title": "数联网",
|
||||
"subTitle": "众创智能体",
|
||||
"centerTitle": "多智能体协同平台",
|
||||
"taskPromptWords": [
|
||||
"如何快速筛选慢性肾脏病药物潜在受试者?",
|
||||
"如何补充“丹芍活血胶囊”不良反应数据?",
|
||||
"如何快速研发用于战场失血性休克的药物?",
|
||||
"二维材料的光电性质受哪些关键因素影响?",
|
||||
"如何通过AI模拟的方法分析材料的微观结构?",
|
||||
"如何分析获取液态金属热力学参数?",
|
||||
"如何解决固态电池的成本和寿命难题?",
|
||||
"如何解决船舶制造中的材料腐蚀难题?",
|
||||
"如何解决船舶制造中流体模拟和建模优化难题?"
|
||||
],
|
||||
"agentRepository": {
|
||||
"storageVersionIdentifier": "1"
|
||||
}
|
||||
}
|
||||
93
src/components/MultiLineTooltip/index.vue
Normal file
93
src/components/MultiLineTooltip/index.vue
Normal file
@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<el-tooltip :disabled="!isOverflow" effect="light" placement="top" :content="text">
|
||||
<div
|
||||
ref="containerRef"
|
||||
class="multi-line-ellipsis"
|
||||
:style="containerStyle"
|
||||
@mouseenter="handleMouseEnter"
|
||||
@mouseleave="handleMouseLeave"
|
||||
>
|
||||
<slot>
|
||||
{{ text }}
|
||||
</slot>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, type HTMLAttributes, nextTick, onMounted, ref } from 'vue'
|
||||
import { ElTooltip } from 'element-plus'
|
||||
|
||||
// 定义组件 props 类型
|
||||
interface Props {
|
||||
text?: string
|
||||
lines?: number
|
||||
maxWidth?: string | number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
text: '',
|
||||
lines: 3,
|
||||
maxWidth: '100%',
|
||||
})
|
||||
|
||||
const isOverflow = ref(false)
|
||||
const containerRef = ref<HTMLElement | null>(null)
|
||||
|
||||
// 计算容器样式
|
||||
const containerStyle = computed(
|
||||
() =>
|
||||
({
|
||||
maxWidth: props.maxWidth,
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
WebkitLineClamp: props.lines,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
lineHeight: '1.5',
|
||||
wordBreak: 'break-all',
|
||||
}) as HTMLAttributes['style'],
|
||||
)
|
||||
|
||||
// 检查文字是否溢出
|
||||
const checkOverflow = (element: HTMLElement): boolean => {
|
||||
// 单行情况下使用宽度判断
|
||||
if (props.lines === 1) {
|
||||
return element.scrollWidth > element.clientWidth
|
||||
}
|
||||
// 多行情况下使用高度判断
|
||||
else {
|
||||
return element.scrollHeight > element.clientHeight
|
||||
}
|
||||
}
|
||||
|
||||
// 鼠标进入处理
|
||||
const handleMouseEnter = (event: MouseEvent) => {
|
||||
const element = event.target as HTMLElement
|
||||
console.log(checkOverflow(element))
|
||||
isOverflow.value = checkOverflow(element)
|
||||
}
|
||||
|
||||
// 鼠标离开处理
|
||||
const handleMouseLeave = () => {
|
||||
isOverflow.value = false
|
||||
}
|
||||
|
||||
// 初始化时检查溢出状态
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
if (containerRef.value) {
|
||||
isOverflow.value = checkOverflow(containerRef.value)
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.multi-line-ellipsis {
|
||||
cursor: default;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
}
|
||||
</style>
|
||||
@ -1,15 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { useConfigStore } from '@/stores'
|
||||
|
||||
defineOptions({
|
||||
name: 'AppHeader'
|
||||
})
|
||||
|
||||
const configStore = useConfigStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-[var(--color-bg-secondary)] h-[60px] relative pl-[27px] font-[900] text-[24px]">
|
||||
<div class="absolute left-0 h-full flex items-center">
|
||||
<img class="w-[36.8px] h-[36.8px] rounded-full mr-[12px]" src="/logo.jpg" alt="logo">
|
||||
<span class="text-[#9E0000]">数联网</span>众创智能体
|
||||
<img class="w-[36.8px] h-[36.8px] rounded-full mr-[12px]" src="/logo.jpg" alt="logo" />
|
||||
<span class="text-[#9E0000]">{{ configStore.config.title }}</span>{{ configStore.config.subTitle }}
|
||||
</div>
|
||||
<div class="text-center h-full w-full tracking-[8.5px] flex items-center justify-center">
|
||||
{{ configStore.config.centerTitle }}
|
||||
</div>
|
||||
<div class="text-center h-full w-full tracking-[8.5px] flex items-center justify-center">多智能体协同平台</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { useAgentsStore } from '@/stores'
|
||||
import { useAgentsStore, useConfigStore } from '@/stores'
|
||||
import api from '@/api'
|
||||
import { changeBriefs } from '@/utils/collaboration_Brief_FrontEnd.ts'
|
||||
import { ElMessage } from 'element-plus'
|
||||
@ -13,6 +13,7 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const agentsStore = useAgentsStore()
|
||||
const configStore = useConfigStore()
|
||||
|
||||
const searchValue = ref('')
|
||||
const triggerOnFocus = ref(true)
|
||||
@ -41,22 +42,10 @@ async function handleSearch() {
|
||||
}
|
||||
}
|
||||
|
||||
const restaurants = ref<string[]>([
|
||||
'如何快速筛选慢性肾脏病药物潜在受试者?',
|
||||
'如何补充“丹芍活血胶囊”不良反应数据?',
|
||||
'如何快速研发用于战场失血性休克的药物?',
|
||||
'二维材料的光电性质受哪些关键因素影响?',
|
||||
'如何通过AI模拟的方法分析材料的微观结构?',
|
||||
'如何分析获取液态金属热力学参数?',
|
||||
'如何解决固态电池的成本和寿命难题?',
|
||||
'如何解决船舶制造中的材料腐蚀难题?',
|
||||
'如何解决船舶制造中流体模拟和建模优化难题?',
|
||||
])
|
||||
const querySearch = (queryString: string, cb: (v: { value: string }[]) => void) => {
|
||||
console.log(queryString)
|
||||
const results = queryString
|
||||
? restaurants.value.filter(createFilter(queryString))
|
||||
: restaurants.value
|
||||
? configStore.config.taskPromptWords.filter(createFilter(queryString))
|
||||
: configStore.config.taskPromptWords
|
||||
// call callback function to return suggestions
|
||||
cb(results.map((item) => ({ value: item })))
|
||||
}
|
||||
|
||||
@ -15,14 +15,19 @@ const md = new MarkdownIt({
|
||||
html: true,
|
||||
linkify: true,
|
||||
typographer: true,
|
||||
breaks: true,
|
||||
})
|
||||
|
||||
function sanitize(str?: string) {
|
||||
if (!str) {
|
||||
return ''
|
||||
}
|
||||
const html = md.render(str)
|
||||
return DOMPurify.sanitize(html)
|
||||
const cleanStr = str
|
||||
.replace(/\\n/g, '\n')
|
||||
.replace(/\n\s*\d+\./g, '\n$&')
|
||||
const html = md.render(cleanStr)
|
||||
return html
|
||||
// return DOMPurify.sanitize(html)
|
||||
}
|
||||
|
||||
interface Data {
|
||||
|
||||
31
src/layout/components/Main/TaskTemplate/TaskSyllabus/Bg.vue
Normal file
31
src/layout/components/Main/TaskTemplate/TaskSyllabus/Bg.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="absolute inset-0 flex items-start gap-[14%]">
|
||||
<!-- 左侧元素 -->
|
||||
<div class="flex-1 relative h-full flex justify-center">
|
||||
<!-- 背景那一根线 -->
|
||||
<div
|
||||
class="h-full bg-[var(--color-bg-tertiary)] w-[5px]"
|
||||
>
|
||||
<!-- 线底部的小圆球 -->
|
||||
<div
|
||||
class="absolute bottom-0 left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[15px] h-[15px] rounded-full"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧元素 -->
|
||||
<div class="flex-1 relative h-full flex justify-center">
|
||||
<!-- 背景那一根线 -->
|
||||
<div
|
||||
class="h-full bg-[var(--color-bg-tertiary)] w-[5px]"
|
||||
>
|
||||
<!-- 线底部的小圆球 -->
|
||||
<div
|
||||
class="absolute bottom-0 left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[15px] h-[15px] rounded-full"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
@ -1,14 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { getAgentMapIcon } from '@/layout/components/config.ts'
|
||||
import {
|
||||
type ConnectArg,
|
||||
Jsplumb,
|
||||
type JsplumbConfig,
|
||||
} from '@/layout/components/Main/TaskTemplate/utils.ts'
|
||||
import { type ConnectArg, Jsplumb } from '@/layout/components/Main/TaskTemplate/utils.ts'
|
||||
import { type IRawStepTask, useAgentsStore } from '@/stores'
|
||||
import { computed } from 'vue'
|
||||
import { AnchorLocations } from '@jsplumb/browser-ui'
|
||||
import MultiLineTooltip from '@/components/MultiLineTooltip/index.vue'
|
||||
|
||||
import Bg from './Bg.vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(el: 'resetAgentRepoLine'): void
|
||||
@ -51,7 +50,7 @@ function handleCurrentTask(task: IRawStepTask, transparent: boolean): ConnectArg
|
||||
config: {
|
||||
type: 'output',
|
||||
transparent,
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -90,124 +89,116 @@ defineExpose({
|
||||
class="flex-1 w-full overflow-y-auto relative"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<div class="flex items-center gap-[14%] w-full px-5 relative" id="task-syllabus">
|
||||
<!-- 流程 -->
|
||||
<div
|
||||
v-if="agentsStore.agentRawPlan.data"
|
||||
class="w-[43%] min-h-full relative flex justify-center"
|
||||
>
|
||||
<!-- 流程内容 -->
|
||||
<div class="relative min-h-full z-10 flex flex-col items-center card-box pb-[100px]">
|
||||
<!-- 背景那一根线 -->
|
||||
<div
|
||||
class="absolute h-full left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[5px] z-[1]"
|
||||
>
|
||||
<!-- 线底部的小圆球 -->
|
||||
<div
|
||||
class="absolute bottom-0 left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[15px] h-[15px] rounded-full"
|
||||
></div>
|
||||
</div>
|
||||
<!-- 固定的标题 -->
|
||||
<div v-show="collaborationProcess.length > 0" class="w-full relative min-h-full" id="task-syllabus">
|
||||
<Bg />
|
||||
|
||||
<div class="w-full flex items-center gap-[14%] mb-[35px]">
|
||||
<div class="flex-1 flex justify-center">
|
||||
<div
|
||||
class="card-item w-[45%] h-[41px] flex justify-center relative z-99 items-center rounded-[20px] bg-[var(--color-bg-tertiary)]"
|
||||
>
|
||||
流程
|
||||
</div>
|
||||
|
||||
<el-card
|
||||
v-for="item in collaborationProcess"
|
||||
:key="item.Id"
|
||||
class="card-item w-full h-[158px] overflow-y-auto relative z-99"
|
||||
:class="agentsStore.currentTask?.StepName === item.StepName ? 'active-card' : ''"
|
||||
shadow="hover"
|
||||
:id="`task-syllabus-flow-${item.Id}`"
|
||||
@click="changeTask(item, true)"
|
||||
>
|
||||
<div class="text-[18px] font-bold text-center">{{ item.StepName }}</div>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<div class="text-[14px] line-clamp-3 text-[var(--color-text-secondary)]">
|
||||
{{ item.TaskContent }}
|
||||
</div>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<div class="flex items-center gap-2 flex-wrap relative">
|
||||
<!-- 连接到智能体库的连接点 -->
|
||||
<div
|
||||
class="absolute left-[-10px] top-1/2 transform -translate-y-1/2"
|
||||
:id="`task-syllabus-flow-agents-${item.Id}`"
|
||||
></div>
|
||||
<el-tooltip
|
||||
v-for="agentSelection in item.AgentSelection"
|
||||
:key="agentSelection"
|
||||
effect="light"
|
||||
placement="right"
|
||||
>
|
||||
<template #content>
|
||||
<div class="w-[150px]">
|
||||
<div class="text-[18px] font-bold">{{ agentSelection }}</div>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<div>
|
||||
{{
|
||||
item.TaskProcess.find((i) => i.AgentName === agentSelection)?.Description
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
class="w-[31px] h-[31px] rounded-full flex items-center justify-center"
|
||||
:style="{ background: getAgentMapIcon(agentSelection).color }"
|
||||
>
|
||||
<svg-icon
|
||||
:icon-class="getAgentMapIcon(agentSelection).icon"
|
||||
color="var(--color-text)"
|
||||
size="24px"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 产出 -->
|
||||
<div
|
||||
v-if="agentsStore.agentRawPlan.data"
|
||||
class="w-[43%] h-full relative flex justify-center"
|
||||
>
|
||||
<div class="min-h-full w-full relative">
|
||||
<!-- 产出内容 -->
|
||||
<div class="min-h-full relative z-10 flex flex-col items-center card-box pb-[100px]">
|
||||
<!-- 背景那一根线 -->
|
||||
<div
|
||||
class="absolute h-full left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[5px] z-[1]"
|
||||
>
|
||||
<!-- 线底部的小圆球 -->
|
||||
<div
|
||||
class="absolute bottom-0 left-1/2 transform -translate-x-1/2 bg-[var(--color-bg-tertiary)] w-[15px] h-[15px] rounded-full"
|
||||
></div>
|
||||
</div>
|
||||
<!-- 固定的标题 -->
|
||||
<div
|
||||
class="card-item w-[45%] h-[41px] flex justify-center items-center rounded-[20px] bg-[var(--color-bg-tertiary)] relative z-99"
|
||||
>
|
||||
产出
|
||||
</div>
|
||||
<div
|
||||
v-for="item in collaborationProcess"
|
||||
:key="item.Id"
|
||||
class="h-[158px] overflow-y-auto flex items-center w-full card-item relative z-99"
|
||||
>
|
||||
<el-card
|
||||
class="card-item w-full relative"
|
||||
shadow="hover"
|
||||
:class="agentsStore.currentTask?.StepName === item.StepName ? 'active-card' : ''"
|
||||
:id="`task-syllabus-output-object-${item.Id}`"
|
||||
>
|
||||
<div class="text-[18px] font-bold text-center">{{ item.OutputObject }}</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 flex justify-center">
|
||||
<div
|
||||
class="card-item w-[45%] h-[41px] flex justify-center relative z-99 items-center rounded-[20px] bg-[var(--color-bg-tertiary)]"
|
||||
>
|
||||
产物
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="item in collaborationProcess"
|
||||
:key="item.Id"
|
||||
class="card-item w-full flex items-center gap-[14%]"
|
||||
>
|
||||
<!-- 流程卡片 -->
|
||||
<el-card
|
||||
class="w-[43%] overflow-y-auto relative z-99 task-syllabus-flow-card"
|
||||
:class="agentsStore.currentTask?.StepName === item.StepName ? 'active-card' : ''"
|
||||
shadow="hover"
|
||||
:id="`task-syllabus-flow-${item.Id}`"
|
||||
@click="changeTask(item, true)"
|
||||
>
|
||||
<MultiLineTooltip placement="right" :text="item.StepName" :lines="2">
|
||||
<div class="text-[18px] font-bold text-center">
|
||||
{{ item.StepName }}
|
||||
</div>
|
||||
</MultiLineTooltip>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<MultiLineTooltip placement="right" :text="item.StepName" :lines="3">
|
||||
<div
|
||||
class="text-[14px] text-[var(--color-text-secondary)]"
|
||||
:title="item.TaskContent"
|
||||
>
|
||||
{{ item.TaskContent }}
|
||||
</div>
|
||||
</MultiLineTooltip>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<div
|
||||
class="flex items-center gap-2 overflow-y-auto flex-wrap relative w-full max-h-[72px]"
|
||||
>
|
||||
<!-- 连接到智能体库的连接点 -->
|
||||
<div
|
||||
class="absolute left-[-10px] top-1/2 transform -translate-y-1/2"
|
||||
:id="`task-syllabus-flow-agents-${item.Id}`"
|
||||
></div>
|
||||
<el-tooltip
|
||||
v-for="agentSelection in item.AgentSelection"
|
||||
:key="agentSelection"
|
||||
effect="light"
|
||||
placement="right"
|
||||
>
|
||||
<template #content>
|
||||
<div class="w-[150px]">
|
||||
<div class="text-[18px] font-bold">{{ agentSelection }}</div>
|
||||
<div class="h-[1px] w-full bg-[#494B51] my-[8px]"></div>
|
||||
<div>
|
||||
{{
|
||||
item.TaskProcess.find((i) => i.AgentName === agentSelection)?.Description
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
class="w-[31px] h-[31px] rounded-full flex items-center justify-center"
|
||||
:style="{ background: getAgentMapIcon(agentSelection).color }"
|
||||
>
|
||||
<svg-icon
|
||||
:icon-class="getAgentMapIcon(agentSelection).icon"
|
||||
color="var(--color-text)"
|
||||
size="24px"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-card>
|
||||
<!-- 产物卡片 -->
|
||||
<el-card
|
||||
class="w-[43%] relative"
|
||||
shadow="hover"
|
||||
:class="agentsStore.currentTask?.StepName === item.StepName ? 'active-card' : ''"
|
||||
:id="`task-syllabus-output-object-${item.Id}`"
|
||||
>
|
||||
<div class="text-[18px] font-bold text-center">{{ item.OutputObject }}</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.task-syllabus-flow-card {
|
||||
:deep(.el-card__body) {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
19
src/main.ts
19
src/main.ts
@ -7,12 +7,17 @@ import './styles/tailwindcss.css'
|
||||
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||
import 'virtual:svg-icons-register'
|
||||
import { initService } from '@/utils/request.ts'
|
||||
import { setupStore } from '@/stores'
|
||||
import { setupStore, useConfigStore } from '@/stores'
|
||||
|
||||
const app = createApp(App)
|
||||
async function init() {
|
||||
const app = createApp(App)
|
||||
setupStore(app)
|
||||
initService()
|
||||
const configStore = useConfigStore()
|
||||
await configStore.initConfig()
|
||||
document.title = configStore.config.centerTitle
|
||||
app.use(router)
|
||||
app.mount('#app')
|
||||
}
|
||||
|
||||
initService()
|
||||
setupStore(app)
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
||||
void init()
|
||||
|
||||
@ -9,3 +9,4 @@ export function setupStore(app: App<Element>) {
|
||||
}
|
||||
|
||||
export * from './modules/agents.ts'
|
||||
export * from './modules/config.ts'
|
||||
|
||||
@ -5,7 +5,7 @@ import { v4 as uuidv4 } from 'uuid'
|
||||
import { store } from '../index'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import type { IExecuteRawResponse } from '@/api'
|
||||
|
||||
import { useConfigStore } from '@/stores/modules/config.ts'
|
||||
|
||||
export interface Agent {
|
||||
Name: string
|
||||
@ -17,12 +17,15 @@ export interface Agent {
|
||||
type HslColorVector = [number, number, number]
|
||||
|
||||
export interface IRichText {
|
||||
template: string;
|
||||
data: Record<string, {
|
||||
text: string;
|
||||
style?: Record<string, string>
|
||||
color?: HslColorVector
|
||||
}>;
|
||||
template: string
|
||||
data: Record<
|
||||
string,
|
||||
{
|
||||
text: string
|
||||
style?: Record<string, string>
|
||||
color?: HslColorVector
|
||||
}
|
||||
>
|
||||
}
|
||||
|
||||
export interface TaskProcess {
|
||||
@ -50,18 +53,45 @@ export interface IRawPlanResponse {
|
||||
'Collaboration Process'?: IRawStepTask[]
|
||||
}
|
||||
|
||||
export const useAgentsStore = defineStore('counter', () => {
|
||||
const agents = useStorage<Agent[]>('agents-v1', [])
|
||||
const storageKey = '$agents' as const
|
||||
|
||||
// 清除所有以 storageKey 开头的 localStorage
|
||||
function clearStorageByVersion() {
|
||||
Object.keys(localStorage)
|
||||
.filter((key) => key.startsWith(storageKey))
|
||||
.forEach((key) => localStorage.removeItem(key))
|
||||
}
|
||||
|
||||
export const useAgentsStore = defineStore('agents', () => {
|
||||
const configStore = useConfigStore()
|
||||
|
||||
const agents = useStorage<Agent[]>(`${storageKey}-repository`, [])
|
||||
function setAgents(agent: Agent[]) {
|
||||
agents.value = agent
|
||||
}
|
||||
|
||||
// 任务搜索的内容
|
||||
const searchValue = useStorage<string>('agent-search-value', '')
|
||||
const searchValue = useStorage<string>(`${storageKey}-search-value`, '')
|
||||
function setSearchValue(value: string) {
|
||||
searchValue.value = value
|
||||
}
|
||||
|
||||
const storageVersionIdentifier = useStorage<string>(`${storageKey}-storage-version-identifier`, '')
|
||||
// 监听 configStore.config.agentRepository.storageVersionIdentifier 改变
|
||||
watch(
|
||||
() => configStore.config.agentRepository.storageVersionIdentifier,
|
||||
(value) => {
|
||||
// value与storageVersionIdentifier不一致清除所有storageKey开头的localStorage
|
||||
if (value !== storageVersionIdentifier.value) {
|
||||
clearStorageByVersion()
|
||||
storageVersionIdentifier.value = value
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
)
|
||||
|
||||
// 当前的展示的任务流程
|
||||
const currentTask = ref<IRawStepTask>()
|
||||
function setCurrentTask(task: IRawStepTask) {
|
||||
@ -72,7 +102,7 @@ export const useAgentsStore = defineStore('counter', () => {
|
||||
|
||||
function setAgentRawPlan(plan: { data?: IRawPlanResponse; loading?: boolean }) {
|
||||
if (plan.data) {
|
||||
plan.data['Collaboration Process'] = plan.data['Collaboration Process']?.map(item => ({
|
||||
plan.data['Collaboration Process'] = plan.data['Collaboration Process']?.map((item) => ({
|
||||
...item,
|
||||
Id: uuidv4(),
|
||||
}))
|
||||
@ -97,7 +127,6 @@ export const useAgentsStore = defineStore('counter', () => {
|
||||
executePlan.value = []
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
agents,
|
||||
setAgents,
|
||||
|
||||
39
src/stores/modules/config.ts
Normal file
39
src/stores/modules/config.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { readConfig } from '@/utils/readJson.ts'
|
||||
import { store } from '@/stores'
|
||||
|
||||
export interface Config {
|
||||
title: string
|
||||
subTitle: string
|
||||
centerTitle: string
|
||||
taskPromptWords: string[]
|
||||
agentRepository: {
|
||||
storageVersionIdentifier: string
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const useConfigStore = defineStore('config', () => {
|
||||
const config = ref<Config>({} as Config)
|
||||
|
||||
// 异步调用readConfig
|
||||
async function initConfig() {
|
||||
config.value = await readConfig<Config>('config.json')
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
config,
|
||||
initConfig
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* 用于在组件外部(如在Pinia Store 中)使用 Pinia 提供的 store 实例。
|
||||
* 官方文档解释了如何在组件外部使用 Pinia Store:
|
||||
* https://pinia.vuejs.org/core-concepts/outside-component-usage.html#using-a-store-outside-of-a-component
|
||||
*/
|
||||
export function useConfigStoreHook() {
|
||||
return useConfigStore(store)
|
||||
}
|
||||
@ -3,7 +3,7 @@ import axios from 'axios'
|
||||
import qs from 'qs'
|
||||
import type { Ref } from 'vue'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 创建 axios 实例
|
||||
let service: AxiosInstance
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user