| | |
| | | font-size: 12px; |
| | | color: #6f859d; |
| | | } |
| | | .editor-textarea .el-textarea__inner { |
| | | min-height: 430px !important; |
| | | .block-textarea .el-textarea__inner { |
| | | min-height: 190px !important; |
| | | font-family: Menlo, Monaco, Consolas, "Liberation Mono", monospace; |
| | | font-size: 12px; |
| | | line-height: 1.7; |
| | | color: #243447; |
| | | background: #fbfdff; |
| | | border-color: #dbe7f3; |
| | | } |
| | | .preview-textarea .el-textarea__inner { |
| | | min-height: 260px !important; |
| | | font-family: Menlo, Monaco, Consolas, "Liberation Mono", monospace; |
| | | font-size: 12px; |
| | | line-height: 1.75; |
| | | color: #203246; |
| | | background: linear-gradient(180deg, #fcfdff 0%, #f7fbff 100%); |
| | | border-color: #d5e3f1; |
| | | } |
| | | .dynamic-context-card { |
| | | margin-top: 10px; |
| | | padding: 10px 12px; |
| | | border-radius: 12px; |
| | | border: 1px solid #e2ebf5; |
| | | background: linear-gradient(180deg, #fdfefe 0%, #f5fbfa 100%); |
| | | color: #5f7288; |
| | | font-size: 12px; |
| | | line-height: 1.75; |
| | | } |
| | | .editor-hint { |
| | | margin-top: 10px; |
| | |
| | | <div class="field-label">备注</div> |
| | | <el-input v-model="editor.memo" size="mini" placeholder="记录这次优化目的或测试结论"></el-input> |
| | | </div> |
| | | <div class="editor-full"> |
| | | <div class="field-label">Prompt内容</div> |
| | | <div> |
| | | <div class="field-label">Base Policy</div> |
| | | <el-input |
| | | class="editor-textarea" |
| | | class="block-textarea" |
| | | type="textarea" |
| | | v-model="editor.content" |
| | | placeholder="在这里编辑 Prompt 内容" |
| | | :autosize="{ minRows: 20, maxRows: 28 }"></el-input> |
| | | v-model="editor.basePolicy" |
| | | placeholder="角色、底线规则、稳定约束" |
| | | :autosize="{ minRows: 8, maxRows: 14 }"></el-input> |
| | | </div> |
| | | <div> |
| | | <div class="field-label">Tool Policy</div> |
| | | <el-input |
| | | class="block-textarea" |
| | | type="textarea" |
| | | v-model="editor.toolPolicy" |
| | | placeholder="什么时候必须查 MCP、怎么使用工具和引用证据" |
| | | :autosize="{ minRows: 8, maxRows: 14 }"></el-input> |
| | | </div> |
| | | <div class="editor-full"> |
| | | <div class="field-label">Output Contract</div> |
| | | <el-input |
| | | class="block-textarea" |
| | | type="textarea" |
| | | v-model="editor.outputContract" |
| | | placeholder="输出格式、结构、禁止事项、工程化要求" |
| | | :autosize="{ minRows: 7, maxRows: 12 }"></el-input> |
| | | </div> |
| | | <div class="editor-full"> |
| | | <div class="field-label">Scene Playbook</div> |
| | | <el-input |
| | | class="block-textarea" |
| | | type="textarea" |
| | | v-model="editor.scenePlaybook" |
| | | placeholder="场景策略,比如任务不执行、设备异常、人工问答等" |
| | | :autosize="{ minRows: 10, maxRows: 16 }"></el-input> |
| | | </div> |
| | | <div class="editor-full"> |
| | | <div class="field-label">组装预览</div> |
| | | <el-input |
| | | class="preview-textarea" |
| | | type="textarea" |
| | | :value="assembledPromptPreview" |
| | | readonly |
| | | :autosize="{ minRows: 12, maxRows: 18 }"></el-input> |
| | | </div> |
| | | <div class="editor-full"> |
| | | <div class="dynamic-context-card"> |
| | | <strong>Dynamic Context</strong><br /> |
| | | 这一层不在这里持久化维护。运行时仍由请求实时注入,比如:用户问题、告警描述、重点设备、日志范围、extraContext,以及 Agent 后续通过 MCP 拉到的实时事实数据。 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | 当前正在编辑草稿 v{{ editor.version || '-' }}。保存只会更新这份草稿,发布后它会替换当前场景的线上版本。 |
| | | </div> |
| | | <div v-else> |
| | | 当前是新草稿。你一新建它就会出现在左侧版本列表里;可以先保存,再单独发布。 |
| | | 当前是新草稿。你现在编辑的是 4 个持久化层:Base Policy、Tool Policy、Output Contract、Scene Playbook;Dynamic Context 继续由运行时注入。 |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | sceneCode: '', |
| | | version: null, |
| | | content: '', |
| | | basePolicy: '', |
| | | toolPolicy: '', |
| | | outputContract: '', |
| | | scenePlaybook: '', |
| | | status: 1, |
| | | published: 0, |
| | | memo: '', |
| | |
| | | return '先从左侧选择场景,或者直接新建草稿。'; |
| | | } |
| | | if (this.editor.published === 1) { |
| | | return '已发布版本只作为查看和复制来源,不直接覆盖修改。'; |
| | | return '当前是已发布版本,4 层内容只能查看;若要修改,先取消发布。'; |
| | | } |
| | | if (this.editor.id) { |
| | | return '正在编辑已有草稿,保存后不会影响线上版本,只有发布才会切换。'; |
| | | return '正在编辑已有草稿。修改的是 Prompt 的 4 个持久化层,保存不会影响线上版本。'; |
| | | } |
| | | return '当前是新草稿,可以自由编辑并保存。'; |
| | | return '当前是新草稿。你可以分层编辑 Prompt,再通过右侧预览检查最终拼接效果。'; |
| | | }, |
| | | assembledPromptPreview: function() { |
| | | return this.composePromptPreview(this.editor); |
| | | }, |
| | | contentCharCount: function() { |
| | | return this.editor.content ? this.editor.content.length : 0; |
| | | return this.assembledPromptPreview ? this.assembledPromptPreview.length : 0; |
| | | }, |
| | | contentLineCount: function() { |
| | | if (!this.editor.content) return 0; |
| | | return this.editor.content.split(/\r?\n/).length; |
| | | if (!this.assembledPromptPreview) return 0; |
| | | return this.assembledPromptPreview.split(/\r?\n/).length; |
| | | } |
| | | }, |
| | | methods: { |
| | |
| | | sceneCode: '', |
| | | version: null, |
| | | content: '', |
| | | basePolicy: '', |
| | | toolPolicy: '', |
| | | outputContract: '', |
| | | scenePlaybook: '', |
| | | status: 1, |
| | | published: 0, |
| | | memo: '', |
| | |
| | | sceneCode: item && item.sceneCode ? item.sceneCode : '', |
| | | version: item && item.version != null ? item.version : null, |
| | | content: item && item.content ? item.content : '', |
| | | basePolicy: item && item.basePolicy ? item.basePolicy : '', |
| | | toolPolicy: item && item.toolPolicy ? item.toolPolicy : '', |
| | | outputContract: item && item.outputContract ? item.outputContract : '', |
| | | scenePlaybook: item && item.scenePlaybook ? item.scenePlaybook : '', |
| | | status: item && item.status != null ? item.status : 1, |
| | | published: item && item.published != null ? item.published : 0, |
| | | memo: item && item.memo ? item.memo : '', |
| | |
| | | }, |
| | | buildLocalDraftKey: function() { |
| | | return 'draft_' + Date.now() + '_' + Math.floor(Math.random() * 100000); |
| | | }, |
| | | composePromptPreview: function(editor) { |
| | | var sections = []; |
| | | var append = function(label, content) { |
| | | var value = content == null ? '' : String(content).trim(); |
| | | if (!value) return; |
| | | sections.push('【' + label + '】\n' + value); |
| | | }; |
| | | append('基础策略', editor && editor.basePolicy); |
| | | append('工具策略', editor && editor.toolPolicy); |
| | | append('输出约定', editor && editor.outputContract); |
| | | append('场景策略', editor && editor.scenePlaybook); |
| | | return sections.join('\n\n'); |
| | | }, |
| | | hasUnsavedEditorForScene: function(sceneCode) { |
| | | return !!(this.editor |
| | |
| | | this.cloneFromTemplate(this.currentPublishedTemplate); |
| | | }, |
| | | buildSavePayload: function() { |
| | | var payloadId = this.editor.id; |
| | | if (this.editor.published === 1) { |
| | | payloadId = null; |
| | | } |
| | | return { |
| | | id: payloadId, |
| | | id: this.editor.id, |
| | | name: this.editor.name, |
| | | sceneCode: this.editor.sceneCode, |
| | | content: this.editor.content, |
| | | basePolicy: this.editor.basePolicy, |
| | | toolPolicy: this.editor.toolPolicy, |
| | | outputContract: this.editor.outputContract, |
| | | scenePlaybook: this.editor.scenePlaybook, |
| | | status: this.editor.status, |
| | | memo: this.editor.memo |
| | | }; |
| | |
| | | self.$message.warning('请选择场景'); |
| | | return; |
| | | } |
| | | if (!self.editor.content || !self.editor.content.trim()) { |
| | | self.$message.warning('Prompt内容不能为空'); |
| | | if (!self.assembledPromptPreview || !self.assembledPromptPreview.trim()) { |
| | | self.$message.warning('至少填写一个 Prompt 分段'); |
| | | return; |
| | | } |
| | | self.saving = true; |