You've already forked agentic-coding-workflow
feat(web): prompt-templates view + chat/admin routes + nav + isAdmin guard
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<AppShell>
|
||||
<div class="space-y-4">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="text-lg font-semibold">
|
||||
Prompt 模板
|
||||
</h2>
|
||||
<NButton
|
||||
type="primary"
|
||||
@click="openCreate"
|
||||
>
|
||||
+ 新增
|
||||
</NButton>
|
||||
</div>
|
||||
<NDataTable
|
||||
:data="templates"
|
||||
:columns="columns"
|
||||
:row-key="rowKey"
|
||||
/>
|
||||
<NModal
|
||||
v-model:show="showForm"
|
||||
preset="card"
|
||||
:title="editing ? '编辑模板' : '新建模板'"
|
||||
style="width: 640px"
|
||||
>
|
||||
<NForm>
|
||||
<NFormItem label="名称">
|
||||
<NInput v-model:value="form.name" />
|
||||
</NFormItem>
|
||||
<NFormItem label="作用域">
|
||||
<NRadioGroup
|
||||
v-model:value="form.scope"
|
||||
:disabled="!!editing"
|
||||
>
|
||||
<NRadio value="user">
|
||||
个人(仅自己可见)
|
||||
</NRadio>
|
||||
<NRadio
|
||||
v-if="auth.isAdmin"
|
||||
value="system"
|
||||
>
|
||||
系统(所有用户可见)
|
||||
</NRadio>
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
<NFormItem label="内容">
|
||||
<NInput
|
||||
v-model:value="form.content"
|
||||
type="textarea"
|
||||
:rows="10"
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<template #footer>
|
||||
<div class="flex justify-end gap-2">
|
||||
<NButton @click="showForm = false">
|
||||
取消
|
||||
</NButton>
|
||||
<NButton
|
||||
type="primary"
|
||||
:loading="saving"
|
||||
@click="save"
|
||||
>
|
||||
保存
|
||||
</NButton>
|
||||
</div>
|
||||
</template>
|
||||
</NModal>
|
||||
</div>
|
||||
</AppShell>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h, onMounted, ref } from 'vue'
|
||||
import {
|
||||
NButton,
|
||||
NDataTable,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NModal,
|
||||
NRadio,
|
||||
NRadioGroup,
|
||||
useDialog,
|
||||
useMessage,
|
||||
} from 'naive-ui'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
|
||||
import AppShell from '@/layouts/AppShell.vue'
|
||||
import { chatApi, type PromptTemplate, type TemplateScope } from '@/api/chat'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
const auth = useAuthStore()
|
||||
const templates = ref<PromptTemplate[]>([])
|
||||
const showForm = ref(false)
|
||||
const editing = ref<PromptTemplate | null>(null)
|
||||
const saving = ref(false)
|
||||
const msg = useMessage()
|
||||
const dlg = useDialog()
|
||||
|
||||
const form = ref<{ name: string; content: string; scope: TemplateScope }>({
|
||||
name: '',
|
||||
content: '',
|
||||
scope: 'user',
|
||||
})
|
||||
|
||||
const columns: DataTableColumns<PromptTemplate> = [
|
||||
{ title: '名称', key: 'name' },
|
||||
{ title: '作用域', key: 'scope' },
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
render: (row) =>
|
||||
h('div', { class: 'flex gap-1' }, [
|
||||
h(
|
||||
NButton,
|
||||
{ size: 'small', onClick: () => openEdit(row) },
|
||||
{ default: () => '编辑' },
|
||||
),
|
||||
h(
|
||||
NButton,
|
||||
{ size: 'small', type: 'error', onClick: () => del(row) },
|
||||
{ default: () => '删除' },
|
||||
),
|
||||
]),
|
||||
},
|
||||
]
|
||||
|
||||
const rowKey = (row: PromptTemplate) => row.id
|
||||
|
||||
onMounted(reload)
|
||||
|
||||
async function reload() {
|
||||
templates.value = await chatApi.listTemplates()
|
||||
}
|
||||
|
||||
function openCreate() {
|
||||
editing.value = null
|
||||
form.value = { name: '', content: '', scope: 'user' }
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
function openEdit(t: PromptTemplate) {
|
||||
editing.value = t
|
||||
form.value = { name: t.name, content: t.content, scope: t.scope }
|
||||
showForm.value = true
|
||||
}
|
||||
|
||||
async function save() {
|
||||
saving.value = true
|
||||
try {
|
||||
if (editing.value) {
|
||||
await chatApi.updateTemplate(editing.value.id, {
|
||||
name: form.value.name,
|
||||
content: form.value.content,
|
||||
})
|
||||
} else {
|
||||
await chatApi.createTemplate({
|
||||
name: form.value.name,
|
||||
content: form.value.content,
|
||||
scope: form.value.scope,
|
||||
})
|
||||
}
|
||||
showForm.value = false
|
||||
await reload()
|
||||
} catch (e) {
|
||||
msg.error(e instanceof Error ? e.message : String(e))
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function del(t: PromptTemplate) {
|
||||
dlg.warning({
|
||||
title: `删除 "${t.name}"?`,
|
||||
positiveText: '删除',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
await chatApi.deleteTemplate(t.id)
|
||||
await reload()
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user