SystemPromptManagement.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <template>
  2. <div class="system-prompt-page">
  3. <el-card>
  4. <div slot="header" class="clearfix">
  5. <span>系统提示词管理</span>
  6. <div style="float:right; display:flex; gap:10px;">
  7. <el-button size="mini" type="info" @click="fetchList">刷新</el-button>
  8. <el-button size="mini" type="primary" @click="showEdit(null)">新增提示词</el-button>
  9. </div>
  10. </div>
  11. <el-form :model="filters" inline size="small" style="margin-bottom:16px;">
  12. <el-form-item label="关键词">
  13. <el-input v-model="filters.keyword" placeholder="搜索标题或键名" clearable @input="fetchList" />
  14. </el-form-item>
  15. </el-form>
  16. <el-table :data="list" border stripe v-loading="loading" empty-text="暂无数据" style="width:100%">
  17. <el-table-column prop="promptKey" label="提示词键" width="160" />
  18. <el-table-column prop="title" label="标题" width="140" />
  19. <el-table-column prop="content" label="内容" min-width="300" show-overflow-tooltip />
  20. <el-table-column prop="version" label="版本" width="60" />
  21. <el-table-column prop="status" label="状态" width="70">
  22. <template slot-scope="{ row }">
  23. <el-tag :type="row.status === 1 ? 'success' : 'info'" size="small">
  24. {{ row.status === 1 ? '启用' : '禁用' }}
  25. </el-tag>
  26. </template>
  27. </el-table-column>
  28. <el-table-column prop="updatedAt" label="更新时间" width="160">
  29. <template slot-scope="{ row }">
  30. {{ row.updatedAt ? formatTime(row.updatedAt) : '-' }}
  31. </template>
  32. </el-table-column>
  33. <el-table-column label="操作" width="180" fixed="right">
  34. <template slot-scope="{ row }">
  35. <el-button type="text" size="small" @click="showEdit(row)">编辑</el-button>
  36. <el-button type="text" size="small" @click="showPreview(row)">预览</el-button>
  37. <el-button type="text" size="small" @click="resetToDefault(row)">重置</el-button>
  38. <el-button type="text" size="small" style="color:#f56c6c" @click="deleteRow(row)">删除</el-button>
  39. </template>
  40. </el-table-column>
  41. </el-table>
  42. <el-pagination
  43. style="margin-top: 16px; text-align: right"
  44. :current-page="page"
  45. :page-size="size"
  46. :total="total"
  47. layout="total, prev, pager, next"
  48. @current-change="handlePageChange"
  49. />
  50. </el-card>
  51. <!-- 编辑弹窗 -->
  52. <el-dialog :visible.sync="dialog.visible" :title="dialog.isEdit ? '编辑提示词' : '新增提示词'" width="700px" :close-on-click-modal="false">
  53. <el-form :model="dialog.form" label-width="100px" size="small">
  54. <el-form-item label="提示词键" :required="!dialog.isEdit">
  55. <el-input v-model="dialog.form.promptKey" placeholder="如 health_coach(英文下划线)" :disabled="dialog.isEdit" />
  56. </el-form-item>
  57. <el-form-item label="标题" required>
  58. <el-input v-model="dialog.form.title" placeholder="如 儿童健康教练" />
  59. </el-form-item>
  60. <el-form-item label="状态">
  61. <el-radio-group v-model="dialog.form.status">
  62. <el-radio :label="1">启用</el-radio>
  63. <el-radio :label="0">禁用</el-radio>
  64. </el-radio-group>
  65. </el-form-item>
  66. <el-form-item label="内容" required>
  67. <el-input v-model="dialog.form.content" type="textarea" :rows="18" placeholder="输入系统提示词内容..." />
  68. </el-form-item>
  69. <el-form-item label="备注">
  70. <el-input v-model="dialog.form.remark" placeholder="用途说明" />
  71. </el-form-item>
  72. </el-form>
  73. <div slot="footer">
  74. <el-button size="small" @click="dialog.visible = false">取消</el-button>
  75. <el-button size="small" type="primary" :loading="saving" @click="savePrompt">保存</el-button>
  76. </div>
  77. </el-dialog>
  78. <!-- 预览弹窗 -->
  79. <el-dialog title="提示词预览" :visible.sync="previewVisible" width="600px">
  80. <el-card shadow="never" style="white-space: pre-wrap; font-family: monospace; font-size: 13px; line-height: 1.8; background: #fafafa;">
  81. {{ previewContent }}
  82. </el-card>
  83. <div slot="footer">
  84. <el-button size="small" @click="previewVisible = false">关闭</el-button>
  85. </div>
  86. </el-dialog>
  87. </div>
  88. </template>
  89. <script>
  90. import { getPromptList, savePrompt, resetPrompt, deletePrompt } from '@/api/systemPrompt'
  91. export default {
  92. name: 'SystemPromptManagement',
  93. data() {
  94. return {
  95. list: [],
  96. loading: false,
  97. filters: { keyword: '' },
  98. page: 1,
  99. size: 20,
  100. total: 0,
  101. dialog: { visible: false, isEdit: false, form: {} },
  102. saving: false,
  103. previewVisible: false,
  104. previewContent: ''
  105. }
  106. },
  107. created() {
  108. this.fetchList()
  109. },
  110. methods: {
  111. formatTime(ts) {
  112. if (!ts) return ''
  113. const d = new Date(ts)
  114. return d.toLocaleString('zh-CN', { hour12: false })
  115. },
  116. async fetchList() {
  117. this.loading = true
  118. try {
  119. const res = await getPromptList({ keyword: this.filters.keyword, page: this.page, size: this.size })
  120. if (res && res.data) {
  121. this.list = res.data.records || []
  122. this.total = res.data.total || 0
  123. }
  124. } finally {
  125. this.loading = false
  126. }
  127. },
  128. showEdit(row) {
  129. this.dialog.isEdit = !!row
  130. this.dialog.form = row ? Object.assign({}, row) : { promptKey: '', title: '', content: '', status: 1, remark: '' }
  131. this.dialog.visible = true
  132. },
  133. async savePrompt() {
  134. const form = this.dialog.form
  135. if (!form.promptKey || !form.title || !form.content) {
  136. this.$message.warning('请填写完整')
  137. return
  138. }
  139. this.saving = true
  140. try {
  141. await savePrompt(form)
  142. this.$message.success('保存成功')
  143. this.dialog.visible = false
  144. this.fetchList()
  145. } finally {
  146. this.saving = false
  147. }
  148. },
  149. async resetToDefault(row) {
  150. this.$confirm('确定要重置为出厂默认内容吗?', '提示', { type: 'warning' }).then(async () => {
  151. await resetPrompt(row.promptKey)
  152. this.$message.success('已重置')
  153. this.fetchList()
  154. }).catch(() => {})
  155. },
  156. deleteRow(row) {
  157. this.$confirm('确定要删除该提示词吗?', '提示', { type: 'warning' }).then(async () => {
  158. await deletePrompt(row.id)
  159. this.$message.success('删除成功')
  160. this.fetchList()
  161. }).catch(() => {})
  162. },
  163. showPreview(row) {
  164. this.previewContent = row.content
  165. this.previewVisible = true
  166. },
  167. handlePageChange(page) {
  168. this.page = page
  169. this.fetchList()
  170. }
  171. }
  172. }
  173. </script>
  174. <style scoped>
  175. .system-prompt-page {
  176. padding: 0;
  177. }
  178. </style>