Files
ruoyi-vue/src/views/system/social-media/prompt-config.vue
2025-11-29 23:39:46 +08:00

290 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="prompt-config-container">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span class="card-title">
<i class="el-icon-setting"></i>
DS提示词模板配置
</span>
<el-button
style="float: right; padding: 3px 0"
type="text"
@click="showHelp = !showHelp">
{{ showHelp ? '隐藏帮助' : '显示帮助' }}
</el-button>
</div>
<!-- 帮助说明 -->
<el-collapse-transition>
<div v-show="showHelp" class="help-section">
<el-alert
title="使用说明"
type="info"
:closable="false"
show-icon>
<div slot="default">
<p><strong>功能说明</strong></p>
<ul>
<li>配置DSDeepSeekAI的提示词模板用于生成关键词和文案</li>
<li>模板存储在Redis中修改后立即生效</li>
<li>支持占位符%s 用于替换实际内容</li>
<li>删除模板将恢复为系统默认模板</li>
</ul>
<p><strong>模板类型</strong></p>
<ul>
<li><strong>关键词提取模板</strong>用于提取商品关键词占位符%s = 商品名称</li>
<li><strong>小红书文案模板</strong>用于生成小红书风格文案占位符%s = 商品名称%s = 价格信息%s = 关键词</li>
<li><strong>抖音文案模板</strong>用于生成抖音风格文案占位符%s = 商品名称%s = 价格信息%s = 关键词</li>
<li><strong>通用文案模板</strong>用于生成通用风格文案占位符%s = 商品名称%s = 价格信息%s = 关键词</li>
</ul>
</div>
</el-alert>
</div>
</el-collapse-transition>
<!-- 模板列表 -->
<div class="template-list">
<el-tabs v-model="activeTab" type="border-card">
<el-tab-pane
v-for="(template, key) in templates"
:key="key"
:label="getTemplateLabel(key)"
:name="key">
<div class="template-editor">
<div class="template-info">
<el-alert
:title="template.description"
type="info"
:closable="false"
show-icon
style="margin-bottom: 15px;">
</el-alert>
<div class="template-status">
<el-tag :type="template.isDefault ? 'info' : 'success'" size="small">
{{ template.isDefault ? '使用默认模板' : '使用自定义模板' }}
</el-tag>
<el-button
v-if="!template.isDefault"
type="text"
size="small"
icon="el-icon-refresh-left"
@click="handleResetTemplate(key)"
style="margin-left: 10px;">
恢复默认
</el-button>
</div>
</div>
<el-input
v-model="template.template"
type="textarea"
:rows="12"
placeholder="请输入提示词模板..."
class="template-textarea">
</el-input>
<div class="template-actions">
<el-button
type="primary"
icon="el-icon-check"
@click="handleSaveTemplate(key)"
:loading="saving[key]">
保存模板
</el-button>
<el-button
icon="el-icon-refresh"
@click="handleLoadTemplate(key)">
重新加载
</el-button>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</el-card>
</div>
</template>
<script>
import { listPromptTemplates, getPromptTemplate, savePromptTemplate, deletePromptTemplate } from '@/api/jarvis/socialMediaPrompt'
export default {
name: 'SocialMediaPromptConfig',
data() {
return {
showHelp: false,
activeTab: 'keywords',
templates: {},
saving: {}
}
},
mounted() {
this.loadTemplates()
},
methods: {
/** 加载所有模板 */
async loadTemplates() {
try {
const res = await listPromptTemplates()
if (res.code === 200 && res.data) {
this.templates = res.data
// 初始化保存状态
Object.keys(this.templates).forEach(key => {
this.$set(this.saving, key, false)
})
} else {
this.$message.error(res.msg || '加载模板失败')
}
} catch (error) {
console.error('加载模板失败', error)
this.$message.error('加载模板失败:' + (error.message || '未知错误'))
}
},
/** 加载单个模板 */
async handleLoadTemplate(key) {
try {
const res = await getPromptTemplate(key)
if (res.code === 200 && res.data) {
this.$set(this.templates, key, res.data)
this.$message.success('重新加载成功')
} else {
this.$message.error(res.msg || '加载失败')
}
} catch (error) {
console.error('加载模板失败', error)
this.$message.error('加载失败:' + (error.message || '未知错误'))
}
},
/** 保存模板 */
async handleSaveTemplate(key) {
const template = this.templates[key]
if (!template || !template.template || template.template.trim() === '') {
this.$message.warning('模板内容不能为空')
return
}
this.$set(this.saving, key, true)
try {
const res = await savePromptTemplate({
key: key,
template: template.template.trim()
})
if (res.code === 200) {
this.$message.success('保存成功!')
// 更新状态
this.$set(template, 'isDefault', false)
// 重新加载以确认
await this.handleLoadTemplate(key)
} else {
this.$message.error(res.msg || '保存失败')
}
} catch (error) {
console.error('保存模板失败', error)
this.$message.error('保存失败:' + (error.message || '未知错误'))
} finally {
this.$set(this.saving, key, false)
}
},
/** 恢复默认模板 */
async handleResetTemplate(key) {
try {
await this.$confirm('确定要恢复默认模板吗?自定义模板将被删除。', '提示', {
type: 'warning'
})
const res = await deletePromptTemplate(key)
if (res.code === 200) {
this.$message.success('已恢复默认模板')
// 重新加载
await this.handleLoadTemplate(key)
} else {
this.$message.error(res.msg || '恢复失败')
}
} catch (error) {
if (error !== 'cancel') {
console.error('恢复默认模板失败', error)
this.$message.error('恢复失败:' + (error.message || '未知错误'))
}
}
},
/** 获取模板标签 */
getTemplateLabel(key) {
const labels = {
'keywords': '关键词提取',
'content:xhs': '小红书文案',
'content:douyin': '抖音文案',
'content:both': '通用文案'
}
return labels[key] || key
}
}
}
</script>
<style scoped>
.prompt-config-container {
padding: 20px;
}
.card-title {
font-size: 18px;
font-weight: bold;
}
.help-section {
margin-bottom: 20px;
}
.help-section ul {
margin: 10px 0;
padding-left: 20px;
}
.help-section li {
margin: 5px 0;
}
.template-list {
margin-top: 20px;
}
.template-editor {
padding: 20px;
}
.template-info {
margin-bottom: 20px;
}
.template-status {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.template-textarea {
margin-bottom: 20px;
}
.template-textarea >>> .el-textarea__inner {
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 13px;
line-height: 1.6;
}
.template-actions {
text-align: right;
}
.template-actions .el-button {
margin-left: 10px;
}
</style>