提示词保存
This commit is contained in:
489
frontend/app/web-gold/src/views/system/StyleSettings.vue
Normal file
489
frontend/app/web-gold/src/views/system/StyleSettings.vue
Normal file
@@ -0,0 +1,489 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, reactive, h } from 'vue'
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
import { EditOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue'
|
||||
import { UserPromptApi } from '@/api/userPrompt'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 表格数据
|
||||
const dataSource = ref([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
showTotal: (total) => `共 ${total} 条`,
|
||||
})
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
name: '',
|
||||
category: '',
|
||||
status: undefined,
|
||||
})
|
||||
|
||||
// 编辑弹窗
|
||||
const editModalVisible = ref(false)
|
||||
const editForm = reactive({
|
||||
id: null,
|
||||
name: '',
|
||||
content: '',
|
||||
category: '',
|
||||
status: 1,
|
||||
_originalRecord: null, // 保存原始记录,用于更新时获取必需字段
|
||||
})
|
||||
const editFormRef = ref(null)
|
||||
|
||||
// 表格列定义
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '内容',
|
||||
dataIndex: 'content',
|
||||
key: 'content',
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => {
|
||||
if (!text) return '-'
|
||||
const preview = text.length > 100 ? text.substring(0, 100) + '...' : text
|
||||
return h('span', { title: text }, preview)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
dataIndex: 'category',
|
||||
key: 'category',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
customRender: ({ text }) => {
|
||||
return h('span', {
|
||||
style: {
|
||||
color: text === 1 ? '#52c41a' : '#ff4d4f',
|
||||
},
|
||||
}, text === 1 ? '启用' : '禁用')
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '使用次数',
|
||||
dataIndex: 'useCount',
|
||||
key: 'useCount',
|
||||
width: 120,
|
||||
sorter: (a, b) => (a.useCount || 0) - (b.useCount || 0),
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 180,
|
||||
customRender: ({ text }) => {
|
||||
return text ? dayjs(text).format('YYYY-MM-DD HH:mm:ss') : '-'
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
customRender: ({ record }) => {
|
||||
return h('div', { style: { display: 'flex', gap: '8px' } }, [
|
||||
h('a-button', {
|
||||
type: 'link',
|
||||
size: 'small',
|
||||
onClick: () => handleEdit(record),
|
||||
}, [
|
||||
h(EditOutlined),
|
||||
'编辑',
|
||||
]),
|
||||
h('a-button', {
|
||||
type: 'link',
|
||||
size: 'small',
|
||||
danger: true,
|
||||
onClick: () => handleDelete(record),
|
||||
}, [
|
||||
h(DeleteOutlined),
|
||||
'删除',
|
||||
]),
|
||||
])
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// 加载数据
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
pageNo: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
name: searchForm.name || undefined,
|
||||
category: searchForm.category || undefined,
|
||||
status: searchForm.status,
|
||||
}
|
||||
|
||||
const response = await UserPromptApi.getUserPromptPage(params)
|
||||
|
||||
if (response && (response.code === 0 || response.code === 200)) {
|
||||
dataSource.value = response.data?.list || []
|
||||
pagination.total = response.data?.total || 0
|
||||
} else {
|
||||
throw new Error(response?.msg || response?.message || '加载失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载提示词列表失败:', error)
|
||||
message.error(error?.message || '加载失败,请稍后重试')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function handleSearch() {
|
||||
pagination.current = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 重置搜索
|
||||
function handleReset() {
|
||||
searchForm.name = ''
|
||||
searchForm.category = ''
|
||||
searchForm.status = undefined
|
||||
pagination.current = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 新增
|
||||
function handleAdd() {
|
||||
editForm.id = null
|
||||
editForm.name = ''
|
||||
editForm.content = ''
|
||||
editForm.category = ''
|
||||
editForm.status = 1
|
||||
editForm._originalRecord = null
|
||||
editModalVisible.value = true
|
||||
}
|
||||
|
||||
// 编辑
|
||||
function handleEdit(record) {
|
||||
editForm.id = record.id
|
||||
editForm.name = record.name || ''
|
||||
editForm.content = record.content || ''
|
||||
editForm.category = record.category || ''
|
||||
editForm.status = record.status ?? 1
|
||||
// 保存原始记录的完整信息,用于更新时传递必需字段
|
||||
editForm._originalRecord = record
|
||||
editModalVisible.value = true
|
||||
}
|
||||
|
||||
// 保存(新增/编辑)
|
||||
async function handleSave() {
|
||||
try {
|
||||
await editFormRef.value.validate()
|
||||
} catch (error) {
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
const payload = {
|
||||
name: editForm.name.trim(),
|
||||
content: editForm.content.trim(),
|
||||
category: editForm.category.trim() || null,
|
||||
status: editForm.status,
|
||||
}
|
||||
|
||||
if (editForm.id) {
|
||||
// 更新:只需要传递要修改的字段,后端会自动填充其他字段
|
||||
payload.id = editForm.id
|
||||
// 注意:sort、useCount、isPublic 等字段后端会自动从数据库获取,无需前端传递
|
||||
|
||||
const response = await UserPromptApi.updateUserPrompt(payload)
|
||||
if (response && (response.code === 0 || response.code === 200)) {
|
||||
message.success('更新成功')
|
||||
editModalVisible.value = false
|
||||
loadData()
|
||||
} else {
|
||||
throw new Error(response?.msg || response?.message || '更新失败')
|
||||
}
|
||||
} else {
|
||||
// 新增:需要包含所有必需字段
|
||||
payload.sort = 0
|
||||
payload.useCount = 0
|
||||
payload.isPublic = false
|
||||
|
||||
const response = await UserPromptApi.createUserPrompt(payload)
|
||||
if (response && (response.code === 0 || response.code === 200)) {
|
||||
message.success('创建成功')
|
||||
editModalVisible.value = false
|
||||
loadData()
|
||||
} else {
|
||||
throw new Error(response?.msg || response?.message || '创建失败')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存提示词失败:', error)
|
||||
message.error(error?.message || '保存失败,请稍后重试')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
function handleDelete(record) {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: `确定要删除提示词"${record.name}"吗?`,
|
||||
onOk: async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const response = await UserPromptApi.deleteUserPrompt(record.id)
|
||||
if (response && (response.code === 0 || response.code === 200)) {
|
||||
message.success('删除成功')
|
||||
loadData()
|
||||
} else {
|
||||
throw new Error(response?.msg || response?.message || '删除失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除提示词失败:', error)
|
||||
message.error(error?.message || '删除失败,请稍后重试')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 分页变化
|
||||
function handleTableChange(pag) {
|
||||
pagination.current = pag.current
|
||||
pagination.pageSize = pag.pageSize
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="style-settings-page">
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">风格设置</h1>
|
||||
<p class="page-description">管理您的提示词模板,用于内容创作和风格定制</p>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<!-- 搜索表单 -->
|
||||
<div class="search-card card">
|
||||
<a-form :model="searchForm" layout="inline" class="search-form">
|
||||
<a-form-item label="名称">
|
||||
<a-input
|
||||
v-model:value="searchForm.name"
|
||||
placeholder="请输入提示词名称"
|
||||
allow-clear
|
||||
style="width: 200px"
|
||||
@pressEnter="handleSearch"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分类">
|
||||
<a-input
|
||||
v-model:value="searchForm.category"
|
||||
placeholder="请输入分类"
|
||||
allow-clear
|
||||
style="width: 200px"
|
||||
@pressEnter="handleSearch"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态">
|
||||
<a-select
|
||||
v-model:value="searchForm.status"
|
||||
placeholder="请选择状态"
|
||||
allow-clear
|
||||
style="width: 120px"
|
||||
>
|
||||
<a-select-option :value="1">启用</a-select-option>
|
||||
<a-select-option :value="0">禁用</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleSearch">搜索</a-button>
|
||||
<a-button @click="handleReset">重置</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
|
||||
<!-- 操作栏 -->
|
||||
<div class="action-bar">
|
||||
<a-button type="primary" @click="handleAdd">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
新增提示词
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="table-card card">
|
||||
<a-table
|
||||
:dataSource="dataSource"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
rowKey="id"
|
||||
@change="handleTableChange"
|
||||
:scroll="{ x: 1200 }"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<a-modal
|
||||
v-model:visible="editModalVisible"
|
||||
:title="editForm.id ? '编辑提示词' : '新增提示词'"
|
||||
width="800px"
|
||||
@ok="handleSave"
|
||||
@cancel="editModalVisible = false"
|
||||
>
|
||||
<a-form
|
||||
ref="editFormRef"
|
||||
:model="editForm"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
>
|
||||
<a-form-item
|
||||
label="名称"
|
||||
name="name"
|
||||
:rules="[{ required: true, message: '请输入提示词名称' }]"
|
||||
>
|
||||
<a-input v-model:value="editForm.name" placeholder="请输入提示词名称" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="内容"
|
||||
name="content"
|
||||
:rules="[{ required: true, message: '请输入提示词内容' }]"
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value="editForm.content"
|
||||
placeholder="请输入提示词内容"
|
||||
:rows="8"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="分类" name="category">
|
||||
<a-input v-model:value="editForm.category" placeholder="请输入分类(可选)" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="状态"
|
||||
name="status"
|
||||
:rules="[{ required: true, message: '请选择状态' }]"
|
||||
>
|
||||
<a-radio-group v-model:value="editForm.status">
|
||||
<a-radio :value="1">启用</a-radio>
|
||||
<a-radio :value="0">禁用</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.style-settings-page {
|
||||
padding: 24px;
|
||||
min-height: calc(100vh - 70px);
|
||||
background: var(--color-bg);
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.page-description {
|
||||
font-size: 14px;
|
||||
color: var(--color-text-secondary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-card);
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.search-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.table-card {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.ant-table) {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
:deep(.ant-table-thead > tr > th) {
|
||||
background: var(--color-surface);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
:deep(.ant-table-tbody > tr > td) {
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
:deep(.ant-table-tbody > tr:hover > td) {
|
||||
background: var(--color-bg);
|
||||
}
|
||||
|
||||
:deep(.ant-pagination) {
|
||||
margin: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user