|
|
@@ -0,0 +1,271 @@
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ v-model="dialogVisible"
|
|
|
+ :title="$t('views.application.memory.title')"
|
|
|
+ width="700px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ >
|
|
|
+ <div class="memory-container">
|
|
|
+ <!-- 记忆开关 -->
|
|
|
+ <div class="mb-16">
|
|
|
+ <el-switch
|
|
|
+ v-model="memoryEnable"
|
|
|
+ :active-text="$t('views.application.memory.enable')"
|
|
|
+ @change="handleEnableChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 记忆列表 -->
|
|
|
+ <div v-if="memoryEnable" class="memory-list">
|
|
|
+ <div class="flex-between mb-16">
|
|
|
+ <el-input
|
|
|
+ v-model="searchQuery"
|
|
|
+ :placeholder="$t('views.application.memory.searchPlaceholder')"
|
|
|
+ clearable
|
|
|
+ @keyup.enter="handleSearch"
|
|
|
+ style="width: 300px"
|
|
|
+ >
|
|
|
+ <template #prefix>
|
|
|
+ <el-icon><Search /></el-icon>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <el-button type="primary" @click="handleCreate">
|
|
|
+ {{ $t('views.application.memory.add') }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-table :data="memoryList" v-loading="loading" style="width: 100%">
|
|
|
+ <el-table-column prop="content" :label="$t('views.application.memory.content')" show-overflow-tooltip />
|
|
|
+ <el-table-column prop="memory_type" :label="$t('views.application.memory.type')" width="120">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag :type="getMemoryTypeTag(row.memory_type)">
|
|
|
+ {{ getMemoryTypeLabel(row.memory_type) }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="is_enabled" :label="$t('views.application.memory.status')" width="100">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-switch v-model="row.is_enabled" @change="handleStatusChange(row)" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :label="$t('common.operation')" width="150">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button type="primary" link @click="handleEdit(row)">
|
|
|
+ {{ $t('common.edit') }}
|
|
|
+ </el-button>
|
|
|
+ <el-button type="danger" link @click="handleDelete(row)">
|
|
|
+ {{ $t('common.delete') }}
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="dialogVisible = false">
|
|
|
+ {{ $t('common.close') }}
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 创建/编辑对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="editDialogVisible"
|
|
|
+ :title="editingMemory ? $t('views.application.memory.edit') : $t('views.application.memory.add')"
|
|
|
+ width="500px"
|
|
|
+ >
|
|
|
+ <el-form :model="editForm" label-position="top">
|
|
|
+ <el-form-item :label="$t('views.application.memory.type')">
|
|
|
+ <el-select v-model="editForm.memory_type" style="width: 100%">
|
|
|
+ <el-option label="对话记忆" value="DIALOGUE" />
|
|
|
+ <el-option label="关键词记忆" value="KEYWORD" />
|
|
|
+ <el-option label="摘要记忆" value="SUMMARY" />
|
|
|
+ <el-option label="自定义记忆" value="CUSTOM" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item :label="$t('views.application.memory.content')">
|
|
|
+ <el-input
|
|
|
+ v-model="editForm.content"
|
|
|
+ type="textarea"
|
|
|
+ :rows="4"
|
|
|
+ :placeholder="$t('views.application.memory.contentPlaceholder')"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="editDialogVisible = false">
|
|
|
+ {{ $t('common.cancel') }}
|
|
|
+ </el-button>
|
|
|
+ <el-button type="primary" @click="handleSave" :loading="saving">
|
|
|
+ {{ $t('common.save') }}
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, onMounted } from 'vue'
|
|
|
+import { Search } from '@element-plus/icons-vue'
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
+import {
|
|
|
+ getMemoryList,
|
|
|
+ createMemory,
|
|
|
+ updateMemory,
|
|
|
+ deleteMemory,
|
|
|
+ searchMemories,
|
|
|
+} from '@/api/application/memory'
|
|
|
+import type { ApplicationMemory } from '@/api/application/memory'
|
|
|
+
|
|
|
+const props = defineProps<{
|
|
|
+ applicationId: string
|
|
|
+}>()
|
|
|
+
|
|
|
+const dialogVisible = ref(false)
|
|
|
+const editDialogVisible = ref(false)
|
|
|
+const loading = ref(false)
|
|
|
+const saving = ref(false)
|
|
|
+const memoryEnable = ref(false)
|
|
|
+const searchQuery = ref('')
|
|
|
+const memoryList = ref<ApplicationMemory[]>([])
|
|
|
+const editingMemory = ref<ApplicationMemory | null>(null)
|
|
|
+
|
|
|
+const editForm = ref({
|
|
|
+ memory_type: 'DIALOGUE',
|
|
|
+ content: '',
|
|
|
+})
|
|
|
+
|
|
|
+const getMemoryTypeTag = (type: string) => {
|
|
|
+ const map: Record<string, string> = {
|
|
|
+ DIALOGUE: '',
|
|
|
+ KEYWORD: 'success',
|
|
|
+ SUMMARY: 'warning',
|
|
|
+ CUSTOM: 'info',
|
|
|
+ }
|
|
|
+ return map[type] || ''
|
|
|
+}
|
|
|
+
|
|
|
+const getMemoryTypeLabel = (type: string) => {
|
|
|
+ const map: Record<string, string> = {
|
|
|
+ DIALOGUE: '对话记忆',
|
|
|
+ KEYWORD: '关键词记忆',
|
|
|
+ SUMMARY: '摘要记忆',
|
|
|
+ CUSTOM: '自定义记忆',
|
|
|
+ }
|
|
|
+ return map[type] || type
|
|
|
+}
|
|
|
+
|
|
|
+const loadMemoryList = async () => {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const res = await getMemoryList(props.applicationId)
|
|
|
+ memoryList.value = res.data || []
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Failed to load memory list:', error)
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleEnableChange = (value: boolean) => {
|
|
|
+ // TODO: 保存记忆开关配置到应用设置
|
|
|
+ if (value) {
|
|
|
+ loadMemoryList()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleSearch = async () => {
|
|
|
+ if (!searchQuery.value) {
|
|
|
+ loadMemoryList()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const res = await searchMemories(props.applicationId, { query: searchQuery.value })
|
|
|
+ memoryList.value = res.data || []
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Failed to search memories:', error)
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleCreate = () => {
|
|
|
+ editingMemory.value = null
|
|
|
+ editForm.value = { memory_type: 'DIALOGUE', content: '' }
|
|
|
+ editDialogVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const handleEdit = (memory: ApplicationMemory) => {
|
|
|
+ editingMemory.value = memory
|
|
|
+ editForm.value = {
|
|
|
+ memory_type: memory.memory_type,
|
|
|
+ content: memory.content,
|
|
|
+ }
|
|
|
+ editDialogVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const handleSave = async () => {
|
|
|
+ if (!editForm.value.content.trim()) {
|
|
|
+ ElMessage.warning('请输入记忆内容')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ saving.value = true
|
|
|
+ try {
|
|
|
+ if (editingMemory.value) {
|
|
|
+ await updateMemory(props.applicationId, editingMemory.value.id, editForm.value)
|
|
|
+ ElMessage.success('更新成功')
|
|
|
+ } else {
|
|
|
+ await createMemory(props.applicationId, editForm.value)
|
|
|
+ ElMessage.success('创建成功')
|
|
|
+ }
|
|
|
+ editDialogVisible.value = false
|
|
|
+ loadMemoryList()
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Failed to save memory:', error)
|
|
|
+ } finally {
|
|
|
+ saving.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleStatusChange = async (memory: ApplicationMemory) => {
|
|
|
+ try {
|
|
|
+ await updateMemory(props.applicationId, memory.id, { is_enabled: memory.is_enabled })
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Failed to update memory status:', error)
|
|
|
+ memory.is_enabled = !memory.is_enabled
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleDelete = async (memory: ApplicationMemory) => {
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm('确定要删除这条记忆吗?', '提示', {
|
|
|
+ type: 'warning',
|
|
|
+ })
|
|
|
+ await deleteMemory(props.applicationId, memory.id)
|
|
|
+ ElMessage.success('删除成功')
|
|
|
+ loadMemoryList()
|
|
|
+ } catch (error) {
|
|
|
+ if (error !== 'cancel') {
|
|
|
+ console.error('Failed to delete memory:', error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const open = () => {
|
|
|
+ dialogVisible.value = true
|
|
|
+ loadMemoryList()
|
|
|
+}
|
|
|
+
|
|
|
+defineExpose({ open })
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.memory-container {
|
|
|
+ min-height: 400px;
|
|
|
+}
|
|
|
+.memory-list {
|
|
|
+ margin-top: 16px;
|
|
|
+}
|
|
|
+</style>
|