This commit is contained in:
Leo
2025-11-29 23:39:46 +08:00
parent 1234ad42a4
commit 86e8fefb97
2 changed files with 324 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
import request from '@/utils/request'
// 获取提示词模板列表
export function listPromptTemplates() {
return request({
url: '/jarvis/social-media/prompt/list',
method: 'get'
})
}
// 获取单个提示词模板
export function getPromptTemplate(key) {
return request({
url: '/jarvis/social-media/prompt/' + key,
method: 'get'
})
}
// 保存提示词模板
export function savePromptTemplate(data) {
return request({
url: '/jarvis/social-media/prompt/save',
method: 'post',
data: data
})
}
// 删除提示词模板(恢复默认)
export function deletePromptTemplate(key) {
return request({
url: '/jarvis/social-media/prompt/' + key,
method: 'delete'
})
}

View File

@@ -0,0 +1,289 @@
<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>