|
|
@@ -12,116 +12,122 @@
|
|
|
<div
|
|
|
class="select_btn"
|
|
|
v-for="category in categories"
|
|
|
- :key="category.value"
|
|
|
- :class="{ selected: selectedCategory === category.value }"
|
|
|
- @click="selectCategory(category.value)"
|
|
|
+ :key="category"
|
|
|
+ :class="{ selected: selectedCategory === category }"
|
|
|
+ @click="selectCategory(category)"
|
|
|
>
|
|
|
- {{ category.label }}
|
|
|
+ {{ category }}
|
|
|
</div>
|
|
|
</a-space>
|
|
|
</div>
|
|
|
<div class="agents-list-container" ref="agentsListContainer">
|
|
|
- <div class="agent-card" v-for="app in filteredApps" :key="app.app.id" @click="handleAgentClick(app)">
|
|
|
- <!-- <Icon :name="app.category" alt="icon" class="agent-icon" /> -->
|
|
|
- <div class="agent-icon" :style="{ backgroundColor: app.app.icon_background }">
|
|
|
- {{ app.app.icon }}
|
|
|
- </div>
|
|
|
+ <div class="agent-card" v-for="app in filter_agent_list" :key="app.id" @click="handleAgentClick(app)">
|
|
|
+ <Icon :name="app.mode" alt="icon" class="agent-icon" />
|
|
|
<div class="agent-info">
|
|
|
- <div class="agent-title">{{ app.app.name }}</div>
|
|
|
- <div class="agent-subtitle">{{ app.description || '暂无描述' }}</div>
|
|
|
+ <div class="agent-title">{{ app.name }}</div>
|
|
|
+ <div class="agent-subtitle">{{ app.description }}</div>
|
|
|
</div>
|
|
|
- <a-button shape="circle" class="arrow-button" @click="toAddApp(app)">
|
|
|
+ <a-button shape="circle" class="arrow-button">
|
|
|
<icon-arrow-right />
|
|
|
</a-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <modal_add v-if="show_model" :show_model="show_model" :app="model_app" @close="closeModal"></modal_add>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, onMounted, nextTick, onUnmounted, computed } from 'vue';
|
|
|
-import { fetchApps, fetchAppInfo, getSearchApps } from '../../apis/home';
|
|
|
+import { ref, onMounted, nextTick, onUnmounted } from 'vue';
|
|
|
+import { fetchApps, fetchAppInfo } from '../../apis/home';
|
|
|
import { Message } from '../../3rd-libs/arco-vue-libs';
|
|
|
import Icon from '../../components/Icon/Icon.vue';
|
|
|
import { getConfigField } from '../../config'; // 假设 getConfigField 是从某处导入的
|
|
|
import { access_token } from '../../base/storage';
|
|
|
-import modal_add from './modal_add.vue';
|
|
|
|
|
|
const categories = ref([]);
|
|
|
-const recommendedApps = ref([]);
|
|
|
+const agent_list = ref([]);
|
|
|
+const filter_agent_list = ref([]);
|
|
|
const agentsListContainer = ref(null);
|
|
|
+const selectedCategory = ref('全部'); // 默认选中“全部”
|
|
|
const baseurl = getConfigField('API_BASE_URL');
|
|
|
-const selectedCategory = ref('推荐'); // 默认选中“全部”
|
|
|
+const page = ref(1); // 当前页码
|
|
|
+const limit = 30; // 每页显示的数量
|
|
|
|
|
|
const loadApps = async () => {
|
|
|
try {
|
|
|
- const response = await getSearchApps();
|
|
|
- recommendedApps.value = response.recommended_apps || [];
|
|
|
- // categories.value = response.categories || [];
|
|
|
- categories.value = (response.categories || []).map((item) => {
|
|
|
- if (item === 'Assistant') {
|
|
|
- return {
|
|
|
- label: '助手',
|
|
|
- value: 'Assistant'
|
|
|
- };
|
|
|
- } else if (item === 'HR') {
|
|
|
- return {
|
|
|
- label: '人力资源',
|
|
|
- value: 'HR'
|
|
|
- };
|
|
|
- } else if (item === 'Programming') {
|
|
|
- return {
|
|
|
- label: '编程',
|
|
|
- value: 'Programming'
|
|
|
- };
|
|
|
- } else if (item === 'Writing') {
|
|
|
- return {
|
|
|
- label: '写作',
|
|
|
- value: 'Writing'
|
|
|
- };
|
|
|
- } else {
|
|
|
- return {
|
|
|
- label: item,
|
|
|
- value: item
|
|
|
- };
|
|
|
- }
|
|
|
- });
|
|
|
- categories.value.unshift({
|
|
|
- label: '推荐',
|
|
|
- value: '推荐'
|
|
|
- });
|
|
|
+ const params = {
|
|
|
+ page: page.value,
|
|
|
+ limit,
|
|
|
+ name: ''
|
|
|
+ };
|
|
|
+ const response = await fetchApps(params);
|
|
|
+ agent_list.value = [...agent_list.value, ...response.data]; // 追加新数据
|
|
|
+
|
|
|
+ // 遍历 mode 并去重
|
|
|
+ const modes = new Set(agent_list.value.map((app) => app.mode));
|
|
|
+ const modeMap = {
|
|
|
+ workflow: '工作流',
|
|
|
+ 'advanced-chat': '高级助手',
|
|
|
+ chat: '聊天助手',
|
|
|
+ 'agent-chat': 'Agent'
|
|
|
+ };
|
|
|
+ categories.value = ['全部', ...Array.from(modes).map((mode) => modeMap[mode] || mode)];
|
|
|
+
|
|
|
+ filterApps(); // 加载应用后进行初次筛选
|
|
|
} catch (error) {
|
|
|
Message.error('加载数据失败');
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+const loadMoreApps = async () => {
|
|
|
+ page.value += 1; // 增加页码
|
|
|
+ await loadApps(); // 加载更多数据
|
|
|
+};
|
|
|
+
|
|
|
+const filterApps = () => {
|
|
|
+ if (selectedCategory.value === '全部') {
|
|
|
+ filter_agent_list.value = agent_list.value;
|
|
|
+ } else {
|
|
|
+ const modeMap = {
|
|
|
+ 工作流: 'workflow',
|
|
|
+ 高级聊天: 'advanced-chat',
|
|
|
+ 聊天助手: 'chat',
|
|
|
+ Agent: 'agent-chat'
|
|
|
+ };
|
|
|
+ const selectedMode = modeMap[selectedCategory.value] || selectedCategory.value;
|
|
|
+ filter_agent_list.value = agent_list.value.filter((app) => app.mode === selectedMode);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
const adjustContainerHeight = () => {
|
|
|
if (agentsListContainer.value) {
|
|
|
const windowHeight = window.innerHeight;
|
|
|
const containerTop = agentsListContainer.value.getBoundingClientRect().top;
|
|
|
- agentsListContainer.value.style.height = `${windowHeight - containerTop - 55}px`; // 底部的间距
|
|
|
+ agentsListContainer.value.style.height = `${windowHeight - containerTop - 80}px`; // 20px 是底部的间距
|
|
|
}
|
|
|
};
|
|
|
-const model_app = ref(null);
|
|
|
-const show_model = ref(false);
|
|
|
-const toAddApp = async (app) => {
|
|
|
- model_app.value = app;
|
|
|
- show_model.value = true;
|
|
|
-};
|
|
|
-const closeModal = () => {
|
|
|
- show_model.value = false;
|
|
|
- model_app.value = null;
|
|
|
+
|
|
|
+const handleScroll = () => {
|
|
|
+ if (agentsListContainer.value) {
|
|
|
+ const { scrollTop, scrollHeight, clientHeight } = agentsListContainer.value;
|
|
|
+ if (scrollTop + clientHeight >= scrollHeight - 10) {
|
|
|
+ // 距离底部10px时加载更多
|
|
|
+ loadMoreApps();
|
|
|
+ }
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
loadApps();
|
|
|
nextTick(adjustContainerHeight);
|
|
|
window.addEventListener('resize', adjustContainerHeight);
|
|
|
+ agentsListContainer.value.addEventListener('scroll', handleScroll);
|
|
|
});
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
window.removeEventListener('resize', adjustContainerHeight);
|
|
|
+ if (agentsListContainer.value) {
|
|
|
+ agentsListContainer.value.removeEventListener('scroll', handleScroll);
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
const createAgent = () => {
|
|
|
@@ -130,21 +136,32 @@ const createAgent = () => {
|
|
|
window.open(workflowUrl, '_blank');
|
|
|
};
|
|
|
|
|
|
-const filteredApps = computed(() => {
|
|
|
- if (selectedCategory.value === '推荐') {
|
|
|
- return recommendedApps.value;
|
|
|
- }
|
|
|
- return recommendedApps.value.filter((app) => app.category === selectedCategory.value);
|
|
|
-});
|
|
|
-
|
|
|
const selectCategory = (category) => {
|
|
|
selectedCategory.value = category;
|
|
|
+ filterApps(); // 选择分类后进行筛选
|
|
|
};
|
|
|
|
|
|
const handleAgentClick = async (app) => {
|
|
|
- // TODO 弹窗
|
|
|
+ const appId = app.id;
|
|
|
+
|
|
|
+ let end = '';
|
|
|
+ if (app.workflow) {
|
|
|
+ end = 'workflow';
|
|
|
+ } else {
|
|
|
+ end = 'configuration';
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // const { site } = await fetchAppInfo(appId);
|
|
|
+ const dify_token = access_token.get();
|
|
|
+ // const chatUrl = `${baseurl}/chat/${site.code}?token=${dify_token}`;
|
|
|
+ const chatUrl = `${baseurl}/app/${appId}/${end}`;
|
|
|
+ window.open(chatUrl, '_blank');
|
|
|
+ } catch (error) {
|
|
|
+ Message.error('加载数据失败');
|
|
|
+ }
|
|
|
};
|
|
|
</script>
|
|
|
+
|
|
|
<style scoped>
|
|
|
.window {
|
|
|
width: 90%;
|
|
|
@@ -213,16 +230,9 @@ const handleAgentClick = async (app) => {
|
|
|
}
|
|
|
|
|
|
.agent-icon {
|
|
|
- min-width: 40px;
|
|
|
- max-width: 40px;
|
|
|
- min-height: 40px;
|
|
|
- max-height: 40px;
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
margin-right: 16px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- font-size: 18px;
|
|
|
- overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.agent-info {
|