feat: add quick action buttons (preview/undo/reset) to sidebar
Sidebar now has 快捷操作 section matching Streamlit app functionality: - 预览 — sends "预览报表" to preview current JRXML - 撤销 — sends "撤销上一步修改" to revert last change - 重置 — sends "重新来,清空当前报表" to reset session Session store now tracks history_states for undo availability check.
This commit is contained in:
@@ -114,7 +114,7 @@ async function handleSend(text: string, files: File[]) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-layout">
|
<div class="app-layout">
|
||||||
<Sidebar />
|
<Sidebar @quickAction="(text) => handleSend(text, [])" />
|
||||||
|
|
||||||
<main class="main-area">
|
<main class="main-area">
|
||||||
<div class="chat-container" ref="chatContainer">
|
<div class="chat-container" ref="chatContainer">
|
||||||
|
|||||||
@@ -6,6 +6,22 @@ import { useChatStore } from '../stores/chat'
|
|||||||
const session = useSessionStore()
|
const session = useSessionStore()
|
||||||
const chat = useChatStore()
|
const chat = useChatStore()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
quickAction: [text: string]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
function handlePreview() {
|
||||||
|
emit('quickAction', '预览报表')
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleUndo() {
|
||||||
|
emit('quickAction', '撤销上一步修改')
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleReset() {
|
||||||
|
emit('quickAction', '重新来,清空当前报表')
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
session.loadSessions()
|
session.loadSessions()
|
||||||
})
|
})
|
||||||
@@ -63,6 +79,26 @@ async function handleDelete() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="sidebar-section" v-if="session.currentId">
|
||||||
|
<div class="section-title">快捷操作</div>
|
||||||
|
<div class="quick-actions">
|
||||||
|
<button
|
||||||
|
class="btn-action btn-preview"
|
||||||
|
:disabled="!session.hasJrxml"
|
||||||
|
@click="handlePreview"
|
||||||
|
>预览</button>
|
||||||
|
<button
|
||||||
|
class="btn-action btn-undo"
|
||||||
|
:disabled="!session.hasHistory"
|
||||||
|
@click="handleUndo"
|
||||||
|
>撤销</button>
|
||||||
|
<button
|
||||||
|
class="btn-action btn-reset"
|
||||||
|
@click="handleReset"
|
||||||
|
>重置</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="sidebar-section" v-if="session.currentJrxml || session.versions.length > 0">
|
<div class="sidebar-section" v-if="session.currentJrxml || session.versions.length > 0">
|
||||||
<div class="section-title">下载</div>
|
<div class="section-title">下载</div>
|
||||||
<a
|
<a
|
||||||
@@ -207,6 +243,60 @@ async function handleDelete() {
|
|||||||
color: #1e1e2e;
|
color: #1e1e2e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-action {
|
||||||
|
flex: 1;
|
||||||
|
padding: 6px 8px;
|
||||||
|
border: 1px solid #45475a;
|
||||||
|
background: #313244;
|
||||||
|
color: #cdd6f4;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
transition: background 0.15s, border-color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-action:hover:not(:disabled) {
|
||||||
|
background: #45475a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-action:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-preview {
|
||||||
|
border-color: #89b4fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-preview:hover:not(:disabled) {
|
||||||
|
background: #89b4fa;
|
||||||
|
color: #1e1e2e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-undo {
|
||||||
|
border-color: #f9e2af;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-undo:hover:not(:disabled) {
|
||||||
|
background: #f9e2af;
|
||||||
|
color: #1e1e2e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-reset {
|
||||||
|
border-color: #f38ba8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-reset:hover:not(:disabled) {
|
||||||
|
background: #f38ba8;
|
||||||
|
color: #1e1e2e;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-download {
|
.btn-download {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
|
|||||||
@@ -9,8 +9,12 @@ export const useSessionStore = defineStore('session', () => {
|
|||||||
const currentId = ref<string>('')
|
const currentId = ref<string>('')
|
||||||
const currentName = ref<string>('')
|
const currentName = ref<string>('')
|
||||||
const versions = ref<any[]>([])
|
const versions = ref<any[]>([])
|
||||||
|
const historyStates = ref<any[]>([])
|
||||||
const currentJrxml = ref<string>('')
|
const currentJrxml = ref<string>('')
|
||||||
|
|
||||||
|
const hasJrxml = computed(() => !!currentJrxml.value)
|
||||||
|
const hasHistory = computed(() => historyStates.value.length > 0)
|
||||||
|
|
||||||
const sortedSessions = computed(() =>
|
const sortedSessions = computed(() =>
|
||||||
[...sessions.value].sort((a, b) =>
|
[...sessions.value].sort((a, b) =>
|
||||||
new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
|
new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
|
||||||
@@ -43,6 +47,7 @@ export const useSessionStore = defineStore('session', () => {
|
|||||||
const state = data.agent_state
|
const state = data.agent_state
|
||||||
currentJrxml.value = state.current_jrxml || ''
|
currentJrxml.value = state.current_jrxml || ''
|
||||||
versions.value = state.jrxml_versions || []
|
versions.value = state.jrxml_versions || []
|
||||||
|
historyStates.value = state.history_states || []
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('加载会话失败:', e)
|
console.error('加载会话失败:', e)
|
||||||
}
|
}
|
||||||
@@ -61,11 +66,12 @@ export const useSessionStore = defineStore('session', () => {
|
|||||||
function refreshFromState(agentState: Record<string, any>) {
|
function refreshFromState(agentState: Record<string, any>) {
|
||||||
currentJrxml.value = agentState.current_jrxml || currentJrxml.value
|
currentJrxml.value = agentState.current_jrxml || currentJrxml.value
|
||||||
versions.value = agentState.jrxml_versions || versions.value
|
versions.value = agentState.jrxml_versions || versions.value
|
||||||
|
historyStates.value = agentState.history_states || historyStates.value
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sessions, currentId, currentName, versions, currentJrxml,
|
sessions, currentId, currentName, versions, historyStates, currentJrxml,
|
||||||
sortedSessions, currentSession,
|
hasJrxml, hasHistory, sortedSessions, currentSession,
|
||||||
loadSessions, createSession, switchSession, deleteCurrent, refreshFromState,
|
loadSessions, createSession, switchSession, deleteCurrent, refreshFromState,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user