2025-07-23 17:41:28 +08:00
|
|
|
<template>
|
2025-08-08 15:44:51 +08:00
|
|
|
<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>
|
2025-07-28 14:53:59 +08:00
|
|
|
<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>
|
2025-07-28 14:53:59 +08:00
|
|
|
<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>
|
2025-07-28 14:53:59 +08:00
|
|
|
<el-form-item :label="t('vabI18n.prologue.openingContent')">
|
2025-08-08 15:44:51 +08:00
|
|
|
<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>
|
2025-07-28 14:53:59 +08:00
|
|
|
<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>
|
2025-07-28 14:53:59 +08:00
|
|
|
<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">
|
2025-08-08 15:44:51 +08:00
|
|
|
<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>
|
2025-07-28 14:53:59 +08:00
|
|
|
|
|
|
|
<!-- 新增推荐问题弹窗 -->
|
|
|
|
<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">
|
2025-08-08 15:44:51 +08:00
|
|
|
<el-form-item :label="t('vabI18n.prologue.dialog.questionContent')">
|
2025-07-28 14:53:59 +08:00
|
|
|
<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>
|
|
|
|
|
2025-08-08 15:44:51 +08:00
|
|
|
</div>
|
2025-07-23 17:41:28 +08:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2025-08-08 15:44:51 +08:00
|
|
|
import { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
|
2025-07-23 17:41:28 +08:00
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
2025-07-28 14:53:59 +08:00
|
|
|
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',
|
2025-08-08 15:44:51 +08:00
|
|
|
// 添加这个配置确保组件在路由切换时正确处理
|
|
|
|
inheritAttrs: false,
|
2025-07-23 17:41:28 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
const form = ref({
|
|
|
|
chatType: '1', // 默认选中 '故障诊断'
|
|
|
|
content: '',
|
|
|
|
})
|
|
|
|
|
|
|
|
const recommendations = ref([]) // 推荐问题列表
|
|
|
|
const currentRecommendation = ref({ questionContent: '' }) // 当前正在编辑的推荐问题
|
2025-07-28 14:53:59 +08:00
|
|
|
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
|
2025-07-28 14:53:59 +08:00
|
|
|
ElMessage.success(t('vabI18n.prologue.message.loadSuccess'))
|
2025-08-08 15:44:51 +08:00
|
|
|
await safeLoadRecommendations() // 获取推荐问题列表
|
2025-07-23 17:41:28 +08:00
|
|
|
} else {
|
|
|
|
form.value.content = ''
|
2025-07-28 14:53:59 +08:00
|
|
|
ElMessage.error(t('vabI18n.prologue.message.notFound'))
|
2025-07-23 17:41:28 +08:00
|
|
|
}
|
|
|
|
} catch (error) {
|
2025-07-28 14:53:59 +08:00
|
|
|
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) {
|
2025-07-28 14:53:59 +08:00
|
|
|
ElMessage.error(t('vabI18n.prologue.message.loadFailedMess'))
|
2025-07-23 17:41:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 监听 chatType 的变化,动态请求并更新 content 和推荐问题内容
|
|
|
|
watch(
|
|
|
|
() => form.value.chatType,
|
|
|
|
() => {
|
2025-08-08 15:44:51 +08:00
|
|
|
safeLoad()
|
2025-07-23 17:41:28 +08:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
// 保存修改后的内容
|
|
|
|
const save = () => {
|
2025-07-28 14:53:59 +08:00
|
|
|
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)
|
2025-07-28 14:53:59 +08:00
|
|
|
ElMessage.success(t('vabI18n.prologue.message.saveSuccess'))
|
2025-07-23 17:41:28 +08:00
|
|
|
} catch (error) {
|
2025-07-28 14:53:59 +08:00
|
|
|
ElMessage.error(t('vabI18n.prologue.message.saveFailed'))
|
2025-07-23 17:41:28 +08:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 新增推荐问题
|
|
|
|
const addRecommend = () => {
|
2025-07-28 14:53:59 +08:00
|
|
|
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) => {
|
2025-07-28 14:53:59 +08:00
|
|
|
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) => {
|
2025-07-28 14:53:59 +08:00
|
|
|
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 删除推荐问题
|
2025-07-28 14:53:59 +08:00
|
|
|
ElMessage.success(t('vabI18n.prologue.message.deleteSuccess'))
|
2025-08-08 15:44:51 +08:00
|
|
|
await safeLoadRecommendations() // 重新加载推荐问题列表
|
2025-07-23 17:41:28 +08:00
|
|
|
} catch (error) {
|
2025-07-28 14:53:59 +08:00
|
|
|
ElMessage.error(t('vabI18n.prologue.message.deleteFailed'))
|
2025-07-23 17:41:28 +08:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-08-08 15:44:51 +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
|
|
|
// 在组件加载时获取初始的开场白内容
|
2025-08-08 15:44:51 +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>
|
2025-08-08 15:44:51 +08:00
|
|
|
|
|
|
|
<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>
|