ai-manus/chat-client/src/views/permission/prologueManage/index.vue

266 lines
9.3 KiB
Vue
Raw Normal View History

2025-07-23 17:41:28 +08:00
<template>
<div v-if="isComponentActive" class="prologue-manage-container">
2025-07-23 17:41:28 +08:00
<el-card>
<el-form :model="form" label-width="120px">
<el-form-item>
<el-button type="primary" @click="load">{{t('vabI18n.prologue.query')}}</el-button>
<el-button type="success" @click="save">{{t('vabI18n.prologue.save')}}</el-button>
2025-07-23 17:41:28 +08:00
</el-form-item>
<el-form-item :label="t('vabI18n.prologue.chatType')">
<el-select v-model="form.chatType" :placeholder="t('vabI18n.prologue.placeholder.selectType')">
<el-option :label="t('vabI18n.prologue.chatTypes.1')" value="1" />
<el-option :label="t('vabI18n.prologue.chatTypes.2')" value="2" />
<el-option :label="t('vabI18n.prologue.chatTypes.3')" value="3" />
<el-option :label="t('vabI18n.prologue.chatTypes.4')" value="4" />
<el-option :label="t('vabI18n.prologue.chatTypes.5')" value="5" />
2025-07-23 17:41:28 +08:00
</el-select>
</el-form-item>
<el-form-item :label="t('vabI18n.prologue.openingContent')">
<el-input type="textarea" v-model="form.content" :rows="8"></el-input>
2025-07-23 17:41:28 +08:00
</el-form-item>
<!-- 新增推荐问题 -->
<el-form-item>
<el-button type="primary" @click="addRecommend">{{t('vabI18n.prologue.addRecommend')}}</el-button>
2025-07-23 17:41:28 +08:00
</el-form-item>
<!-- 推荐问题列表 -->
<el-table :data="recommendations" style="width: 100%" border>
<el-table-column :label="t('vabI18n.prologue.recommendation')" prop="questionContent" />
<el-table-column :label="t('vabI18n.prologue.action')" width="180">
2025-07-23 17:41:28 +08:00
<template v-slot="scope">
<el-button size="small" @click="editRecommend(scope.row)">{{t('vabI18n.prologue.edit')}}</el-button>
<el-button size="small" type="danger" @click="deleteRecommend(scope.row)">{{t('vabI18n.prologue.delete')}}</el-button>
2025-07-23 17:41:28 +08:00
</template>
</el-table-column>
</el-table>
</el-form>
</el-card>
<!-- 新增推荐问题弹窗 -->
<el-dialog v-model="dialogVisible" :title="t('vabI18n.prologue.dialog.addTitle')">
<el-form :model="newRecommendForm" label-width="120px">
<el-form-item :label="t('vabI18n.prologue.dialog.questionContent')">
<el-input v-model="newRecommendForm.questionContent" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">{{t('vabI18n.prologue.dialog.cancel')}}</el-button>
<el-button type="primary" @click="saveNewRecommend">{{t('vabI18n.prologue.dialog.save')}}</el-button>
</span>
</el-dialog>
<!-- 编辑推荐问题弹窗 -->
<el-dialog v-model="editdialogVisible" :title="t('vabI18n.prologue.dialog.editTitle')">
<el-form :model="currentRecommendation" label-width="120px">
<el-form-item :label="t('vabI18n.prologue.dialog.questionContent')">
<el-input v-model="currentRecommendation.questionContent" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editdialogVisible = false">{{t('vabI18n.prologue.dialog.cancel')}}</el-button>
<el-button type="primary" @click="saveEditRecommend">{{t('vabI18n.prologue.dialog.save')}}</el-button>
</span>
</el-dialog>
</div>
2025-07-23 17:41:28 +08:00
</template>
<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
2025-07-23 17:41:28 +08:00
import { ElMessage, ElMessageBox } from 'element-plus'
import { getRemark, saveRemark, getRecommendations, editRecommendation, deleteRecommendation, addRecommendation } from '@/api/prologue'
2025-07-23 17:41:28 +08:00
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
defineOptions({
name: 'prologueManage',
// 添加这个配置确保组件在路由切换时正确处理
inheritAttrs: false,
2025-07-23 17:41:28 +08:00
})
const form = ref({
chatType: '1', // 默认选中 '故障诊断'
content: '',
})
const recommendations = ref([]) // 推荐问题列表
const currentRecommendation = ref({ questionContent: '' }) // 当前正在编辑的推荐问题
const dialogVisible = ref(false) // 控制新增推荐问题弹窗显示
const editdialogVisible = ref(false) // 控制编辑推荐问题弹窗显示
const newRecommendForm = ref({ //新增推荐问题的表单
questionContent: '',
chatType: form.value.chatType,
})
2025-07-23 17:41:28 +08:00
// 查询开场白内容
const load = async () => {
try {
const res = await getRemark(form.value.chatType) // 根据 chatType 获取开场白
if (res.data) {
form.value.content = res.data.content
ElMessage.success(t('vabI18n.prologue.message.loadSuccess'))
await safeLoadRecommendations() // 获取推荐问题列表
2025-07-23 17:41:28 +08:00
} else {
form.value.content = ''
ElMessage.error(t('vabI18n.prologue.message.notFound'))
2025-07-23 17:41:28 +08:00
}
} catch (error) {
ElMessage.error(t('vabI18n.prologue.message.loadFail'))
2025-07-23 17:41:28 +08:00
}
}
// 查询推荐问题列表
const loadRecommendations = async () => {
try {
const res = await getRecommendations(form.value.chatType) // 使用 chatType 获取推荐问题
if (res.data) {
console.log('recommend questions return data:', res.data)
recommendations.value = res.data // 确保 res.data 是推荐问题列表
}
} catch (error) {
ElMessage.error(t('vabI18n.prologue.message.loadFailedMess'))
2025-07-23 17:41:28 +08:00
}
}
// 监听 chatType 的变化,动态请求并更新 content 和推荐问题内容
watch(
() => form.value.chatType,
() => {
safeLoad()
2025-07-23 17:41:28 +08:00
}
)
// 保存修改后的内容
const save = () => {
ElMessageBox.confirm(t('vabI18n.prologue.confirm.save'), t('vabI18n.prologue.confirm.tips'), {
confirmButtonText: t('vabI18n.prologue.dialog.confirm'),
cancelButtonText: t('vabI18n.prologue.dialog.cancel'),
2025-07-23 17:41:28 +08:00
type: 'warning',
}).then(async () => {
try {
await saveRemark(form.value)
ElMessage.success(t('vabI18n.prologue.message.saveSuccess'))
2025-07-23 17:41:28 +08:00
} catch (error) {
ElMessage.error(t('vabI18n.prologue.message.saveFailed'))
2025-07-23 17:41:28 +08:00
}
})
}
// 新增推荐问题
const addRecommend = () => {
newRecommendForm.value = { questionContent: '', chatType: form.value.chatType } // 清空表单并绑定当前 chatType
dialogVisible.value = true // 显示新增推荐问题的弹窗
}
// 保存新增的推荐问题
const saveNewRecommend = async () => {
try {
// 保存推荐问题时,将 chatType 一起提交
await addRecommendation(newRecommendForm.value) // 调用 API 保存推荐问题
ElMessage.success(t('vabI18n.prologue.message.addSuccess'))
dialogVisible.value = false // 关闭弹窗
await loadRecommendations() // 重新加载推荐问题列表
} catch (error) {
ElMessage.error(t('vabI18n.prologue.message.addFailed'))
}
2025-07-23 17:41:28 +08:00
}
// 编辑推荐问题
const editRecommend = (row: any) => {
currentRecommendation.value = { ...row } // 填充编辑框
editdialogVisible.value = true
}
// 保存编辑的推荐问题
const saveEditRecommend = async () => {
try {
// 保存推荐问题时,将 chatType 一起提交
await editRecommendation(currentRecommendation.value) // 调用 API 保存推荐问题
ElMessage.success(t('vabI18n.prologue.message.editSuccess'))
editdialogVisible.value = false // 关闭弹窗
await loadRecommendations() // 重新加载推荐问题列表
} catch (error) {
ElMessage.error(t('vabI18n.prologue.message.editFailed'))
}
2025-07-23 17:41:28 +08:00
}
// 删除推荐问题
const deleteRecommend = (row: any) => {
ElMessageBox.confirm(t('vabI18n.prologue.confirm.delete'), t('vabI18n.prologue.confirm.tips'), {
confirmButtonText: t('vabI18n.prologue.dialog.confirm'),
cancelButtonText: t('vabI18n.prologue.dialog.cancel'),
2025-07-23 17:41:28 +08:00
type: 'warning',
}).then(async () => {
try {
await deleteRecommendation(row.id) // 根据 id 删除推荐问题
ElMessage.success(t('vabI18n.prologue.message.deleteSuccess'))
await safeLoadRecommendations() // 重新加载推荐问题列表
2025-07-23 17:41:28 +08:00
} catch (error) {
ElMessage.error(t('vabI18n.prologue.message.deleteFailed'))
2025-07-23 17:41:28 +08:00
}
})
}
// 用于防止组件销毁后异步请求仍然执行
const isComponentActive = ref(true)
// 安全的异步操作包装器
const safeAsyncOperation = async (operation: () => Promise<void>) => {
if (!isComponentActive.value) return
try {
await operation()
} catch (error) {
if (isComponentActive.value) {
console.error('Async operation failed:', error)
}
}
}
// 修改异步函数以使用安全包装器
const safeLoad = () => safeAsyncOperation(load)
const safeLoadRecommendations = () => safeAsyncOperation(loadRecommendations)
2025-07-23 17:41:28 +08:00
// 在组件加载时获取初始的开场白内容
onMounted(() => {
nextTick(() => {
safeLoad()
})
})
// 组件卸载前清理
onBeforeUnmount(() => {
isComponentActive.value = false
// 重置所有响应式数据
form.value = {
chatType: '1',
content: '',
}
recommendations.value = []
dialogVisible.value = false
editdialogVisible.value = false
})
2025-07-23 17:41:28 +08:00
</script>
<style lang="scss" scoped>
.prologue-manage-container {
width: 100%;
min-height: 100vh;
padding: 20px;
.el-card {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
}
.dialog-footer {
text-align: right;
}
.el-table {
margin-top: 20px;
}
}
</style>