Compare commits

...

1 Commits

Author SHA1 Message Date
57702bd82d 修改编辑器界面
Some checks failed
DevStar Studio CI/CD Pipeline / DevStarStudio-CICD-Pipeline (pull_request) Has been cancelled
2025-12-27 14:07:02 +08:00

View File

@@ -8,6 +8,10 @@ import {renderAnsi} from '../render/ansi.ts';
import {POST, DELETE} from '../modules/fetch.ts';
import type {IntervalId} from '../types.ts';
import {toggleFullScreen} from '../utils.ts';
import {createMonaco} from '../features/codeeditor.ts';
import type MonacoNamespace from 'monaco-editor';
type IStandaloneCodeEditor = MonacoNamespace.editor.IStandaloneCodeEditor;
// see "models/actions/status.go", if it needs to be used somewhere else, move it to a shared file like "types/actions.ts"
type RunStatus = 'unknown' | 'waiting' | 'running' | 'success' | 'failure' | 'cancelled' | 'skipped' | 'blocked';
@@ -123,6 +127,7 @@ export default defineComponent({
isRunningWorkflow: false,
hasDraftContent: false,
draftTimestamp: null as Date | null,
monacoEditor: null as IStandaloneCodeEditor | null,
commitMessage: '',
isCommittingWorkflow: false,
@@ -548,9 +553,85 @@ export default defineComponent({
} finally {
this.isLoadingWorkflow = false;
}
// Initialize Monaco editor if the editor is still open
if (this.showWorkflowEditor) {
// Use a small timeout to allow Vue to re-render the v-else block
setTimeout(() => {
this.initMonacoEditor();
}, 100);
}
},
async initMonacoEditor() {
// 1. Dispose existing editor if any
if (this.monacoEditor) {
this.monacoEditor.dispose();
this.monacoEditor = null;
}
// 2. Poll for textarea element (max 20 attempts, 50ms interval)
let textarea: HTMLTextAreaElement | null = null;
for (let i = 0; i < 20; i++) {
textarea = document.querySelector('#workflow-content-textarea') as HTMLTextAreaElement;
if (textarea) break;
await new Promise(resolve => setTimeout(resolve, 50));
}
if (!textarea) {
console.error('Failed to find workflow textarea for Monaco initialization');
return;
}
try {
// 3. Create Monaco Editor
const {editor} = await createMonaco(textarea, this.workflowPath || 'workflow.yml', {
language: 'yaml',
wordWrap: 'on',
automaticLayout: true,
minimap: {enabled: false},
lineNumbers: 'on',
scrollBeyondLastLine: false,
});
this.monacoEditor = editor;
// Hide the original textarea so only Monaco is visible
textarea.style.display = 'none';
// Force a layout update to ensure editor fills the container
// This fixes the "10 lines then blank" issue
requestAnimationFrame(() => {
editor.layout();
});
// 4. Set up bidirectional sync and auto-save
let saveTimeout: ReturnType<typeof setTimeout> | null = null;
editor.onDidChangeModelContent(() => {
// Sync content back to Vue data
this.workflowContent = editor.getValue();
// Debounce saveDraft
if (saveTimeout) clearTimeout(saveTimeout);
saveTimeout = setTimeout(() => {
this.saveDraft();
}, 1000);
});
} catch (e) {
console.error('Failed to initialize Monaco editor:', e);
alert('Failed to load code editor: ' + e.message + '. Using simple text area instead.');
// Fallback: make sure textarea is visible if Monaco failed
textarea.style.display = 'block';
}
},
closeWorkflowEditor() {
// Dispose Monaco editor
if (this.monacoEditor) {
this.monacoEditor.dispose();
this.monacoEditor = null;
}
this.showWorkflowEditor = false;
this.workflowContent = '';
this.workflowPath = '';
@@ -817,12 +898,18 @@ export default defineComponent({
{{ locale.changes_auto_saved }}
</span>
</label>
<textarea
v-model="workflowContent"
@input="saveDraft()"
rows="15"
style="font-family: monospace; font-size: 12px;">
</textarea>
<div class="editor-wrapper" style="position: relative; height: 600px; border: 1px solid var(--color-secondary); border-radius: var(--border-radius); overflow: hidden;">
<div v-if="!monacoEditor" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; background: var(--color-body); z-index: 10; pointer-events: none;">
<span class="ui active large text loader">Loading Editor...</span>
</div>
<textarea
id="workflow-content-textarea"
v-model="workflowContent"
@input="saveDraft()"
rows="15"
style="font-family: monospace; font-size: 12px; width: 100%; height: 100%; border: none; padding: 1em; box-sizing: border-box; resize: none;">
</textarea>
</div>
</div>
</div>
</div>
@@ -860,6 +947,13 @@ export default defineComponent({
</div>
</template>
<style scoped>
/* Monaco Editor Container */
:deep(.monaco-editor-container) {
height: 100% !important; /* Force full height of the wrapper */
width: 100% !important;
border-radius: 4px;
}
.action-view-body {
padding-top: 12px;
padding-bottom: 12px;