|
|
@ -2,11 +2,40 @@ |
|
|
const props = defineProps<{ |
|
|
const props = defineProps<{ |
|
|
show: boolean; |
|
|
show: boolean; |
|
|
systemPrompt: string; |
|
|
systemPrompt: string; |
|
|
|
|
|
isCustom: boolean; |
|
|
}>(); |
|
|
}>(); |
|
|
|
|
|
|
|
|
const emit = defineEmits<{ |
|
|
const emit = defineEmits<{ |
|
|
close: []; |
|
|
close: []; |
|
|
|
|
|
save: [systemPrompt: string | null]; |
|
|
}>(); |
|
|
}>(); |
|
|
|
|
|
|
|
|
|
|
|
const editingText = ref(""); |
|
|
|
|
|
const saving = ref(false); |
|
|
|
|
|
|
|
|
|
|
|
watch( |
|
|
|
|
|
() => props.show, |
|
|
|
|
|
(val) => { |
|
|
|
|
|
if (val) { |
|
|
|
|
|
editingText.value = props.systemPrompt; |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
async function handleSave() { |
|
|
|
|
|
saving.value = true; |
|
|
|
|
|
try { |
|
|
|
|
|
const trimmed = editingText.value.trim(); |
|
|
|
|
|
emit("save", trimmed.length > 0 ? trimmed.slice(0, 5000) : null); |
|
|
|
|
|
} finally { |
|
|
|
|
|
saving.value = false; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function handleReset() { |
|
|
|
|
|
editingText.value = ""; |
|
|
|
|
|
emit("save", null); |
|
|
|
|
|
} |
|
|
</script> |
|
|
</script> |
|
|
|
|
|
|
|
|
<template> |
|
|
<template> |
|
|
@ -20,7 +49,29 @@ const emit = defineEmits<{ |
|
|
</button> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
<div class="modal-body"> |
|
|
<div class="modal-body"> |
|
|
<pre class="prompt-content">{{ systemPrompt || "(未设置系统提示词)" }}</pre> |
|
|
<div v-if="isCustom" class="custom-badge"> |
|
|
|
|
|
<Icon name="lucide:check-circle" /> |
|
|
|
|
|
<span>当前使用会话自定义提示词</span> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div v-else class="default-badge"> |
|
|
|
|
|
<Icon name="lucide:info" /> |
|
|
|
|
|
<span>当前使用 Agent 默认提示词,编辑后将覆盖默认值</span> |
|
|
|
|
|
</div> |
|
|
|
|
|
<textarea |
|
|
|
|
|
v-model="editingText" |
|
|
|
|
|
class="prompt-textarea" |
|
|
|
|
|
placeholder="输入系统提示词,留空则使用 Agent 默认" |
|
|
|
|
|
maxlength="5000" |
|
|
|
|
|
/> |
|
|
|
|
|
<div class="char-count">{{ editingText.length }} / 5000</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="modal-footer"> |
|
|
|
|
|
<button class="btn-reset" :disabled="saving" @click="handleReset"> |
|
|
|
|
|
重置为默认 |
|
|
|
|
|
</button> |
|
|
|
|
|
<button class="btn-save" :disabled="saving" @click="handleSave"> |
|
|
|
|
|
{{ saving ? "保存中..." : "保存" }} |
|
|
|
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
@ -90,15 +141,98 @@ const emit = defineEmits<{ |
|
|
padding: 20px; |
|
|
padding: 20px; |
|
|
overflow-y: auto; |
|
|
overflow-y: auto; |
|
|
flex: 1; |
|
|
flex: 1; |
|
|
|
|
|
display: flex; |
|
|
|
|
|
flex-direction: column; |
|
|
|
|
|
gap: 12px; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.prompt-content { |
|
|
.custom-badge, |
|
|
|
|
|
.default-badge { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
gap: 6px; |
|
|
|
|
|
padding: 8px 12px; |
|
|
|
|
|
border-radius: 8px; |
|
|
|
|
|
font-size: 13px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.custom-badge { |
|
|
|
|
|
background: var(--color-surface-soft); |
|
|
|
|
|
color: var(--color-primary); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.default-badge { |
|
|
|
|
|
background: var(--color-surface-soft); |
|
|
|
|
|
color: var(--color-muted); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.prompt-textarea { |
|
|
|
|
|
width: 100%; |
|
|
|
|
|
min-height: 200px; |
|
|
|
|
|
padding: 12px; |
|
|
font-family: "SF Mono", "Fira Code", monospace; |
|
|
font-family: "SF Mono", "Fira Code", monospace; |
|
|
font-size: 13px; |
|
|
font-size: 13px; |
|
|
line-height: 1.6; |
|
|
line-height: 1.6; |
|
|
color: var(--color-body); |
|
|
color: var(--color-body); |
|
|
white-space: pre-wrap; |
|
|
background: var(--color-canvas); |
|
|
word-break: break-word; |
|
|
border: 1px solid var(--color-hairline); |
|
|
margin: 0; |
|
|
border-radius: 8px; |
|
|
|
|
|
resize: vertical; |
|
|
|
|
|
outline: none; |
|
|
|
|
|
transition: border-color 0.15s; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.prompt-textarea:focus { |
|
|
|
|
|
border-color: var(--color-primary); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.char-count { |
|
|
|
|
|
text-align: right; |
|
|
|
|
|
font-size: 12px; |
|
|
|
|
|
color: var(--color-muted); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.modal-footer { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
justify-content: flex-end; |
|
|
|
|
|
gap: 8px; |
|
|
|
|
|
padding: 12px 20px; |
|
|
|
|
|
border-top: 1px solid var(--color-hairline); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.btn-reset, |
|
|
|
|
|
.btn-save { |
|
|
|
|
|
padding: 8px 16px; |
|
|
|
|
|
border-radius: 8px; |
|
|
|
|
|
font-size: 14px; |
|
|
|
|
|
cursor: pointer; |
|
|
|
|
|
transition: all 0.15s; |
|
|
|
|
|
border: 1px solid var(--color-hairline); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.btn-reset { |
|
|
|
|
|
background: var(--color-surface-soft); |
|
|
|
|
|
color: var(--color-muted); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.btn-reset:hover { |
|
|
|
|
|
border-color: var(--color-primary); |
|
|
|
|
|
color: var(--color-ink); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.btn-save { |
|
|
|
|
|
background: var(--color-primary); |
|
|
|
|
|
border-color: var(--color-primary); |
|
|
|
|
|
color: var(--color-on-primary); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.btn-save:hover { |
|
|
|
|
|
opacity: 0.9; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.btn-reset:disabled, |
|
|
|
|
|
.btn-save:disabled { |
|
|
|
|
|
opacity: 0.5; |
|
|
|
|
|
cursor: not-allowed; |
|
|
} |
|
|
} |
|
|
</style> |
|
|
</style> |
|
|
|