mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-09 15:04:06 +08:00
将编辑器历史按钮移至顶栏
This commit is contained in:
parent
9e00a08253
commit
2217685072
@ -1,11 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="command-editor">
|
<div class="command-editor">
|
||||||
<!-- 编程语言栏 -->
|
<div class="command-editor-header">
|
||||||
<CommandLanguageBar
|
<!-- 语言选择器及相关配置 -->
|
||||||
v-model="commandManager.state.currentCommand"
|
<CommandLanguage
|
||||||
:canCommandSave="canCommandSave"
|
v-model="commandManager.state.currentCommand"
|
||||||
@action="handleAction"
|
@action="handleAction"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<CommandActions
|
||||||
|
ref="editorActions"
|
||||||
|
:command-code="currentCommand.features?.code || 'temp'"
|
||||||
|
:can-command-save="canCommandSave"
|
||||||
|
@action="handleAction"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 命令设置栏 -->
|
<!-- 命令设置栏 -->
|
||||||
<CommandConfig
|
<CommandConfig
|
||||||
@ -30,14 +39,6 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 编辑器工具按钮组 -->
|
|
||||||
<EditorTools
|
|
||||||
ref="editorTools"
|
|
||||||
v-show="!isConfigExpanded"
|
|
||||||
:commandCode="currentCommand.features?.code || 'temp'"
|
|
||||||
@restore="restoreHistory"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 可视化编排 -->
|
<!-- 可视化编排 -->
|
||||||
<q-dialog v-model="showComposer" maximized>
|
<q-dialog v-model="showComposer" maximized>
|
||||||
<CommandComposer
|
<CommandComposer
|
||||||
@ -53,12 +54,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineAsyncComponent, ref, computed } from "vue";
|
import { defineAsyncComponent, computed } from "vue";
|
||||||
import CommandConfig from "components/editor/CommandConfig.vue";
|
import CommandConfig from "components/editor/CommandConfig.vue";
|
||||||
import CommandLanguageBar from "components/editor/CommandLanguageBar";
|
|
||||||
import EditorTools from "components/editor/EditorTools";
|
|
||||||
import CommandRunResult from "components/CommandRunResult";
|
import CommandRunResult from "components/CommandRunResult";
|
||||||
import CommandComposer from "components/composer/CommandComposer.vue";
|
import CommandComposer from "components/composer/CommandComposer.vue";
|
||||||
|
import CommandLanguage from "components/editor/CommandLanguage";
|
||||||
|
import CommandActions from "components/editor/CommandActions";
|
||||||
import programs from "js/options/programs.js";
|
import programs from "js/options/programs.js";
|
||||||
import { useCommandManager } from "js/commandManager.js";
|
import { useCommandManager } from "js/commandManager.js";
|
||||||
|
|
||||||
@ -86,9 +87,9 @@ export default {
|
|||||||
CodeEditor,
|
CodeEditor,
|
||||||
CommandConfig,
|
CommandConfig,
|
||||||
CommandRunResult,
|
CommandRunResult,
|
||||||
CommandLanguageBar,
|
CommandLanguage,
|
||||||
|
CommandActions,
|
||||||
CommandComposer,
|
CommandComposer,
|
||||||
EditorTools,
|
|
||||||
},
|
},
|
||||||
emits: ["editorEvent"],
|
emits: ["editorEvent"],
|
||||||
data() {
|
data() {
|
||||||
@ -187,12 +188,15 @@ export default {
|
|||||||
case "insert-text":
|
case "insert-text":
|
||||||
this.$refs.editor.repacleEditorSelection(data);
|
this.$refs.editor.repacleEditorSelection(data);
|
||||||
break;
|
break;
|
||||||
|
case "restore":
|
||||||
|
this.restoreHistory(data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
saveToHistory() {
|
saveToHistory() {
|
||||||
this.$refs.editorTools.tryToSave(
|
this.$refs.editorActions.tryToSave(
|
||||||
this.currentCommand.cmd,
|
this.currentCommand.cmd,
|
||||||
this.currentCommand.program
|
this.currentCommand.program
|
||||||
);
|
);
|
||||||
@ -254,6 +258,34 @@ export default {
|
|||||||
background-color: #1e1e1e;
|
background-color: #1e1e1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.command-editor-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command-editor-header :deep(.q-btn) {
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command-editor-header :deep(.q-btn__content) {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command-editor-header :deep(.q-btn-dropdown__arrow) {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command-editor-header :deep(.q-focus-helper) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command-editor-header :deep(.q-btn:hover) {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
.codeEditor {
|
.codeEditor {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
207
src/components/editor/CommandActions.vue
Normal file
207
src/components/editor/CommandActions.vue
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
<template>
|
||||||
|
<div class="command-actions">
|
||||||
|
<q-btn
|
||||||
|
label="历史"
|
||||||
|
class="action-btn"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
stretch
|
||||||
|
color="primary"
|
||||||
|
:icon="isSaving ? 'check_circle' : 'history'"
|
||||||
|
:class="{ 'saving-animation': isSaving }"
|
||||||
|
@click="$refs.history.open()"
|
||||||
|
></q-btn>
|
||||||
|
<q-btn-dropdown
|
||||||
|
class="special-var-btn"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
stretch
|
||||||
|
label="变量"
|
||||||
|
color="primary"
|
||||||
|
icon="data_object"
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-for="(item, index) in Object.values(specialVars)"
|
||||||
|
:key="index"
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="handleSpecialVarClick(item)"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label class="row items-center justify-between">
|
||||||
|
<div v-text="item.label" />
|
||||||
|
<div v-if="item.onlyCmdTypes" class="row">
|
||||||
|
<q-badge color="grey-9" class="q-ml-xs"> 仅 </q-badge>
|
||||||
|
<q-badge
|
||||||
|
v-for="type in item.onlyCmdTypes"
|
||||||
|
:key="type"
|
||||||
|
class="q-ml-xs"
|
||||||
|
v-text="commandTypes[type].label"
|
||||||
|
color="grey-9"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</q-item-label>
|
||||||
|
<q-tooltip v-if="item.tooltip">
|
||||||
|
{{ item.tooltip }}
|
||||||
|
</q-tooltip>
|
||||||
|
<q-item-label caption>{{ item.desc }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
<q-separator vertical class="q-my-xs" />
|
||||||
|
<q-btn
|
||||||
|
v-if="!isRunCodePage"
|
||||||
|
class="action-btn run-btn"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
stretch
|
||||||
|
color="primary"
|
||||||
|
icon="arrow_back"
|
||||||
|
label="退出"
|
||||||
|
@click="$emit('action', 'back')"
|
||||||
|
></q-btn>
|
||||||
|
<q-btn
|
||||||
|
class="action-btn run-btn"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
color="primary"
|
||||||
|
icon="play_arrow"
|
||||||
|
:label="`运行(${ctrlKey}B)`"
|
||||||
|
@click="$emit('action', 'run')"
|
||||||
|
></q-btn>
|
||||||
|
<q-btn
|
||||||
|
v-if="!isRunCodePage"
|
||||||
|
:disable="!canCommandSave"
|
||||||
|
:color="canCommandSave ? 'primary' : 'grey'"
|
||||||
|
class="action-btn save-btn"
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
icon="save"
|
||||||
|
:label="`保存(${ctrlKey}S)`"
|
||||||
|
@click="$emit('action', 'save')"
|
||||||
|
></q-btn>
|
||||||
|
|
||||||
|
<q-dialog v-model="showUserData">
|
||||||
|
<UserData
|
||||||
|
@insertText="
|
||||||
|
insertSpecialVar($event);
|
||||||
|
showUserData = false;
|
||||||
|
"
|
||||||
|
:showInsertBtn="true"
|
||||||
|
/>
|
||||||
|
</q-dialog>
|
||||||
|
|
||||||
|
<!-- 历史记录组件 -->
|
||||||
|
<EditorHistory
|
||||||
|
ref="history"
|
||||||
|
:command-code="commandCode"
|
||||||
|
@restore="$emit('action', 'restore', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import UserData from "components/popup/UserData.vue";
|
||||||
|
import commandTypes from "js/options/commandTypes.js";
|
||||||
|
import specialVars from "js/options/specialVars.js";
|
||||||
|
import EditorHistory from "components/popup/EditorHistory.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "CommandActions",
|
||||||
|
components: {
|
||||||
|
UserData,
|
||||||
|
EditorHistory,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
canCommandSave: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
commandCode: {
|
||||||
|
type: String,
|
||||||
|
default: "temp",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["action"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
ctrlKey: window.utools.isMacOS() ? "⌘" : "⌃",
|
||||||
|
commandTypes,
|
||||||
|
specialVars,
|
||||||
|
showUserData: false,
|
||||||
|
isSaving: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isRunCodePage() {
|
||||||
|
return this.$route.name === "code";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSpecialVarClick(item) {
|
||||||
|
if (item.label === "{{usr:}}") this.showUserData = true;
|
||||||
|
else this.insertSpecialVar(item.label);
|
||||||
|
},
|
||||||
|
insertSpecialVar(text) {
|
||||||
|
if (!text) return;
|
||||||
|
this.$emit("action", "insert-text", `"${text}"`);
|
||||||
|
},
|
||||||
|
tryToSave(content, program) {
|
||||||
|
const saved = this.$refs.history.tryToSave(content, program);
|
||||||
|
if (saved) this.showSaveAnimation();
|
||||||
|
},
|
||||||
|
showSaveAnimation() {
|
||||||
|
this.isSaving = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.isSaving = false;
|
||||||
|
}, 2000);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.command-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 保存动画 */
|
||||||
|
@keyframes saving {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
30% {
|
||||||
|
transform: scale(1.4);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
transform: scale(0.8);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.saving-animation :deep(.q-icon) {
|
||||||
|
animation: saving 2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
will-change: transform, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 运行按钮动画 */
|
||||||
|
.run-btn:hover :deep(.q-icon) {
|
||||||
|
display: inline-block;
|
||||||
|
animation: leftRight 1.5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 保存按钮动画 */
|
||||||
|
.save-btn:not([disabled]):hover :deep(.q-icon) {
|
||||||
|
display: inline-block;
|
||||||
|
animation: upDown 1.2s infinite;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="command-language-bar">
|
<div class="command-language">
|
||||||
<q-select
|
<q-select
|
||||||
class="q-pl-xs"
|
class="q-pl-xs"
|
||||||
dense
|
dense
|
||||||
@ -39,46 +39,10 @@
|
|||||||
</q-item>
|
</q-item>
|
||||||
</template>
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
<q-btn-group unelevated class="button-group">
|
|
||||||
<q-btn-dropdown
|
|
||||||
class="special-var-btn"
|
|
||||||
dense
|
|
||||||
flat
|
|
||||||
label="变量"
|
|
||||||
color="primary"
|
|
||||||
icon="data_object"
|
|
||||||
>
|
|
||||||
<q-list>
|
|
||||||
<q-item
|
|
||||||
v-for="(item, index) in Object.values(specialVars)"
|
|
||||||
:key="index"
|
|
||||||
clickable
|
|
||||||
v-close-popup
|
|
||||||
@click="handleSpecialVarClick(item)"
|
|
||||||
>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label class="row items-center justify-between">
|
|
||||||
<div v-text="item.label" />
|
|
||||||
<div v-if="item.onlyCmdTypes" class="row">
|
|
||||||
<q-badge color="grey-9" class="q-ml-xs"> 仅 </q-badge>
|
|
||||||
<q-badge
|
|
||||||
v-for="type in item.onlyCmdTypes"
|
|
||||||
:key="type"
|
|
||||||
class="q-ml-xs"
|
|
||||||
v-text="commandTypes[type].label"
|
|
||||||
color="grey-9"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</q-item-label>
|
|
||||||
<q-tooltip v-if="item.tooltip">
|
|
||||||
{{ item.tooltip }}
|
|
||||||
</q-tooltip>
|
|
||||||
<q-item-label caption>{{ item.desc }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-btn-dropdown>
|
|
||||||
|
|
||||||
|
<q-space />
|
||||||
|
|
||||||
|
<q-btn-group unelevated class="button-group">
|
||||||
<template v-if="currentCommand.program === 'quickcommand'">
|
<template v-if="currentCommand.program === 'quickcommand'">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-for="(item, index) in ['help_center', 'view_timeline']"
|
v-for="(item, index) in ['help_center', 'view_timeline']"
|
||||||
@ -177,80 +141,26 @@
|
|||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-btn-dropdown>
|
</q-btn-dropdown>
|
||||||
<q-separator vertical inset />
|
|
||||||
<q-btn
|
|
||||||
v-if="!isRunCodePage"
|
|
||||||
class="action-btn run-btn"
|
|
||||||
dense
|
|
||||||
flat
|
|
||||||
color="primary"
|
|
||||||
icon="arrow_back"
|
|
||||||
label="退出"
|
|
||||||
@click="$emit('action', 'back')"
|
|
||||||
></q-btn>
|
|
||||||
<q-btn
|
|
||||||
class="action-btn run-btn"
|
|
||||||
dense
|
|
||||||
flat
|
|
||||||
color="primary"
|
|
||||||
icon="play_arrow"
|
|
||||||
:label="`运行(${ctrlKey}B)`"
|
|
||||||
@click="$emit('action', 'run')"
|
|
||||||
></q-btn>
|
|
||||||
<q-btn
|
|
||||||
v-if="!isRunCodePage"
|
|
||||||
:disable="!canCommandSave"
|
|
||||||
:color="canCommandSave ? 'primary' : 'grey'"
|
|
||||||
class="action-btn save-btn"
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
icon="save"
|
|
||||||
:label="`保存(${ctrlKey}S)`"
|
|
||||||
@click="$emit('action', 'save')"
|
|
||||||
></q-btn>
|
|
||||||
</q-btn-group>
|
</q-btn-group>
|
||||||
<q-dialog v-model="showUserData">
|
|
||||||
<UserData
|
|
||||||
@insertText="
|
|
||||||
insertSpecialVar($event);
|
|
||||||
showUserData = false;
|
|
||||||
"
|
|
||||||
:showInsertBtn="true"
|
|
||||||
/>
|
|
||||||
</q-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import programs from "js/options/programs.js";
|
import programs from "js/options/programs.js";
|
||||||
import specialVars from "js/options/specialVars.js";
|
|
||||||
import commandTypes from "js/options/commandTypes.js";
|
|
||||||
import UserData from "components/popup/UserData.vue";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "CommandLanguageBar",
|
name: "CommandLanguage",
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
canCommandSave: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue", "action"],
|
emits: ["update:modelValue", "action"],
|
||||||
components: {
|
|
||||||
UserData,
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
programs,
|
programs,
|
||||||
specialVars,
|
|
||||||
commandTypes,
|
|
||||||
isSettingsVisible: false,
|
isSettingsVisible: false,
|
||||||
showUserData: false,
|
|
||||||
ctrlKey: window.utools.isMacOS() ? "⌘" : "⌃",
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -269,10 +179,8 @@ export default {
|
|||||||
this.isSettingsVisible = true;
|
this.isSettingsVisible = true;
|
||||||
}
|
}
|
||||||
if (newProgram === "html") {
|
if (newProgram === "html") {
|
||||||
// 如果是html命令,则设置output为html
|
|
||||||
newCommand.output = "html";
|
newCommand.output = "html";
|
||||||
} else if (this.isRunCodePage) {
|
} else if (this.isRunCodePage) {
|
||||||
// 否则,运行代码页面,恢复output为text
|
|
||||||
newCommand.output = "text";
|
newCommand.output = "text";
|
||||||
}
|
}
|
||||||
const featuresIcon = this.currentCommand.features.icon || "";
|
const featuresIcon = this.currentCommand.features.icon || "";
|
||||||
@ -299,69 +207,24 @@ export default {
|
|||||||
showHelp() {
|
showHelp() {
|
||||||
window.showUb.docs();
|
window.showUb.docs();
|
||||||
},
|
},
|
||||||
handleSpecialVarClick(item) {
|
|
||||||
if (item.label === "{{usr:}}") this.showUserData = true;
|
|
||||||
else this.insertSpecialVar(item.label);
|
|
||||||
},
|
|
||||||
insertSpecialVar(text) {
|
|
||||||
if (!text) return;
|
|
||||||
this.$emit("action", "insert-text", `"${text}"`);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.button-group {
|
.command-language {
|
||||||
padding: 0 5px;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-group :deep(.q-focus-helper) {
|
.command-language :deep(.q-field__control),
|
||||||
display: none;
|
.command-language :deep(.q-field__control > *),
|
||||||
}
|
.command-language :deep(.q-field__native) {
|
||||||
|
|
||||||
.button-group :deep(.q-btn__content) {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-group :deep(.q-btn-dropdown__arrow) {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-group .q-btn:hover {
|
|
||||||
filter: brightness(1.2);
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 运行按钮动画 */
|
|
||||||
.run-btn:hover :deep(.q-icon) {
|
|
||||||
display: inline-block;
|
|
||||||
animation: leftRight 1.5s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 保存按钮动画 */
|
|
||||||
.save-btn:not([disabled]):hover :deep(.q-icon) {
|
|
||||||
display: inline-block;
|
|
||||||
animation: upDown 1.2s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.command-language-bar {
|
|
||||||
background-color: #fffffe;
|
|
||||||
height: 30px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body--dark .command-language-bar {
|
|
||||||
background-color: #1e1e1e;
|
|
||||||
}
|
|
||||||
|
|
||||||
.command-language-bar :deep(.q-field__control),
|
|
||||||
.command-language-bar :deep(.q-field__control > *),
|
|
||||||
.command-language-bar :deep(.q-field__native) {
|
|
||||||
max-height: 30px;
|
max-height: 30px;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.command-language {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -1,49 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="editor-tools">
|
|
||||||
<!-- 历史记录组件 -->
|
|
||||||
<EditorHistory
|
|
||||||
ref="history"
|
|
||||||
:commandCode="commandCode"
|
|
||||||
@restore="$emit('restore', $event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import EditorHistory from "components/popup/EditorHistory.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "EditorTools",
|
|
||||||
components: {
|
|
||||||
EditorHistory,
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
commandCode: {
|
|
||||||
type: String,
|
|
||||||
default: "temp",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["restore"],
|
|
||||||
methods: {
|
|
||||||
showHistory() {
|
|
||||||
this.$refs.history.open();
|
|
||||||
},
|
|
||||||
tryToSave(content, program) {
|
|
||||||
this.$refs.history.tryToSave(content, program);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.editor-tools {
|
|
||||||
position: fixed;
|
|
||||||
right: 24px;
|
|
||||||
bottom: 24px;
|
|
||||||
z-index: 500;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,20 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="editor-history-container">
|
<div class="editor-history-container">
|
||||||
<!-- 渲染默认插槽内容(历史按钮) -->
|
|
||||||
<q-btn
|
|
||||||
round
|
|
||||||
dense
|
|
||||||
class="history-btn"
|
|
||||||
:class="{ saving: isSaving }"
|
|
||||||
icon="history"
|
|
||||||
@click="showHistory"
|
|
||||||
>
|
|
||||||
<div class="save-overlay">
|
|
||||||
<q-icon name="check" />
|
|
||||||
</div>
|
|
||||||
<q-tooltip>历史记录</q-tooltip>
|
|
||||||
</q-btn>
|
|
||||||
|
|
||||||
<q-dialog
|
<q-dialog
|
||||||
v-model="show"
|
v-model="show"
|
||||||
position="right"
|
position="right"
|
||||||
@ -36,7 +21,11 @@
|
|||||||
enter-active-class="fade-in"
|
enter-active-class="fade-in"
|
||||||
leave-active-class="fade-out"
|
leave-active-class="fade-out"
|
||||||
>
|
>
|
||||||
<div v-if="selectedIndex !== null" class="preview-content" :key="selectedIndex">
|
<div
|
||||||
|
v-if="selectedIndex !== null"
|
||||||
|
class="preview-content"
|
||||||
|
:key="selectedIndex"
|
||||||
|
>
|
||||||
<pre>{{ historyList[selectedIndex]?.content || "" }}</pre>
|
<pre>{{ historyList[selectedIndex]?.content || "" }}</pre>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="preview-placeholder" key="placeholder">
|
<div v-else class="preview-placeholder" key="placeholder">
|
||||||
@ -142,8 +131,6 @@ export default {
|
|||||||
historyList: [],
|
historyList: [],
|
||||||
maxHistoryItems: 50,
|
maxHistoryItems: 50,
|
||||||
storagePrefix: "editor_history_",
|
storagePrefix: "editor_history_",
|
||||||
isSaving: false,
|
|
||||||
saveTimer: null,
|
|
||||||
selectedIndex: null,
|
selectedIndex: null,
|
||||||
showClearConfirm: false,
|
showClearConfirm: false,
|
||||||
};
|
};
|
||||||
@ -175,21 +162,7 @@ export default {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const saved = this.saveHistory(content, program);
|
return this.saveHistory(content, program);
|
||||||
if (saved) {
|
|
||||||
this.showSaveAnimation();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
showSaveAnimation() {
|
|
||||||
if (this.saveTimer) {
|
|
||||||
clearTimeout(this.saveTimer);
|
|
||||||
}
|
|
||||||
this.isSaving = true;
|
|
||||||
this.saveTimer = setTimeout(() => {
|
|
||||||
this.isSaving = false;
|
|
||||||
}, 1500);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showHistory() {
|
showHistory() {
|
||||||
@ -497,56 +470,6 @@ export default {
|
|||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-btn {
|
|
||||||
color: #666;
|
|
||||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 3px 3px rgba(0, 0, 0, 0.2);
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.history-btn:hover {
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-overlay {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: var(--q-positive);
|
|
||||||
transform: translateY(100%);
|
|
||||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-overlay i {
|
|
||||||
color: white;
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.history-btn.saving {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.history-btn.saving .save-overlay {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 暗色模式适配 */
|
|
||||||
.body--dark .history-btn {
|
|
||||||
color: #bbb;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.body--dark .history-btn:hover {
|
|
||||||
background: #505050;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 确认对话框样式 */
|
/* 确认对话框样式 */
|
||||||
.confirm-dialog {
|
.confirm-dialog {
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user