1
This commit is contained in:
@@ -19,11 +19,21 @@ export function executeInstructionWithForce(data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getHistory(type, limit) {
|
/**
|
||||||
|
* 获取历史消息记录
|
||||||
|
* @param type request | response
|
||||||
|
* @param limit 条数上限
|
||||||
|
* @param keyword 可选,搜索关键词;传则后端在全部数据中过滤后返回
|
||||||
|
*/
|
||||||
|
export function getHistory(type, limit, keyword) {
|
||||||
|
const params = { type, limit }
|
||||||
|
if (keyword != null && String(keyword).trim() !== '') {
|
||||||
|
params.keyword = String(keyword).trim()
|
||||||
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/jarvis/instruction/history',
|
url: '/jarvis/instruction/history',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: { type, limit }
|
params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,20 +70,34 @@
|
|||||||
<el-option label="500条" :value="500"></el-option>
|
<el-option label="500条" :value="500"></el-option>
|
||||||
<el-option label="1000条" :value="1000"></el-option>
|
<el-option label="1000条" :value="1000"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
<span class="history-label history-search-label">搜索匹配:</span>
|
||||||
|
<el-input
|
||||||
|
v-model="historySearchKeyword"
|
||||||
|
size="small"
|
||||||
|
placeholder="输入关键词,在全部历史数据中搜索"
|
||||||
|
clearable
|
||||||
|
style="width: 240px;"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
@input="onHistorySearchInput"
|
||||||
|
/>
|
||||||
|
<span v-if="historySearchKeyword.trim()" class="history-search-tip">(在全部数据中匹配)</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="history-container">
|
<div class="history-container">
|
||||||
<div class="history-column">
|
<div class="history-column">
|
||||||
<div class="history-header">
|
<div class="history-header">
|
||||||
<span>历史请求(最近 {{ historyLimit }} 条)</span>
|
<span>{{ historySearchKeyword.trim() ? `历史请求(关键词匹配 共 ${displayRequestList.length} 条)` : `历史请求(最近 ${historyLimit} 条)` }}</span>
|
||||||
<el-button size="mini" type="primary" icon="el-icon-refresh" @click="loadHistory" :loading="historyLoading">刷新</el-button>
|
<el-button size="mini" type="primary" icon="el-icon-refresh" @click="loadHistory" :loading="historyLoading">刷新</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="history-content">
|
<div class="history-content" v-loading="displayRequestLoading">
|
||||||
<div v-if="requestHistory.length === 0" class="empty-history">
|
<div v-if="!historySearchKeyword.trim() && requestHistory.length === 0" class="empty-history">
|
||||||
<el-empty description="暂无历史请求" :image-size="80" />
|
<el-empty description="暂无历史请求" :image-size="80" />
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="historySearchKeyword.trim() && displayRequestList.length === 0 && !displayRequestLoading" class="empty-history">
|
||||||
|
<el-empty description="无匹配结果" :image-size="80" />
|
||||||
|
</div>
|
||||||
<div v-else class="history-list">
|
<div v-else class="history-list">
|
||||||
<div v-for="(item, idx) in requestHistory" :key="'req-' + idx" class="history-item">
|
<div v-for="(item, idx) in displayRequestList" :key="'req-' + idx" class="history-item">
|
||||||
<div class="history-item-header">
|
<div class="history-item-header">
|
||||||
<div class="history-time">{{ extractTime(item) }}</div>
|
<div class="history-time">{{ extractTime(item) }}</div>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -102,14 +116,17 @@
|
|||||||
|
|
||||||
<div class="history-column">
|
<div class="history-column">
|
||||||
<div class="history-header">
|
<div class="history-header">
|
||||||
<span>历史响应(最近 {{ historyLimit }} 条)</span>
|
<span>{{ historySearchKeyword.trim() ? `历史响应(关键词匹配 共 ${displayResponseList.length} 条)` : `历史响应(最近 ${historyLimit} 条)` }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="history-content">
|
<div class="history-content" v-loading="displayResponseLoading">
|
||||||
<div v-if="responseHistory.length === 0" class="empty-history">
|
<div v-if="!historySearchKeyword.trim() && responseHistory.length === 0" class="empty-history">
|
||||||
<el-empty description="暂无历史响应" :image-size="80" />
|
<el-empty description="暂无历史响应" :image-size="80" />
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="historySearchKeyword.trim() && displayResponseList.length === 0 && !displayResponseLoading" class="empty-history">
|
||||||
|
<el-empty description="无匹配结果" :image-size="80" />
|
||||||
|
</div>
|
||||||
<div v-else class="history-list">
|
<div v-else class="history-list">
|
||||||
<div v-for="(item, idx) in responseHistory" :key="'res-' + idx" class="history-item">
|
<div v-for="(item, idx) in displayResponseList" :key="'res-' + idx" class="history-item">
|
||||||
<div class="history-item-header">
|
<div class="history-item-header">
|
||||||
|
|
||||||
<div class="history-time">{{ extractTime(item) }}</div>
|
<div class="history-time">{{ extractTime(item) }}</div>
|
||||||
@@ -178,6 +195,11 @@ export default {
|
|||||||
responseHistory: [],
|
responseHistory: [],
|
||||||
historyLoading: false,
|
historyLoading: false,
|
||||||
historyLimit: 50,
|
historyLimit: 50,
|
||||||
|
historySearchKeyword: '', // 历史记录搜索关键词(有值时请求后端在全部数据中搜索)
|
||||||
|
searchRequestList: [], // 服务端返回的请求搜索结果
|
||||||
|
searchResponseList: [], // 服务端返回的响应搜索结果
|
||||||
|
historySearchLoading: false,
|
||||||
|
historySearchTimer: null, // 防抖定时器
|
||||||
// 验证码相关
|
// 验证码相关
|
||||||
verifyDialogVisible: false,
|
verifyDialogVisible: false,
|
||||||
verifyCode: '',
|
verifyCode: '',
|
||||||
@@ -188,6 +210,19 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
// 当前展示的请求列表:有搜索关键词时用服务端搜索结果,否则用本地已加载的 requestHistory
|
||||||
|
displayRequestList() {
|
||||||
|
return this.historySearchKeyword.trim() ? this.searchRequestList : this.requestHistory
|
||||||
|
},
|
||||||
|
displayResponseList() {
|
||||||
|
return this.historySearchKeyword.trim() ? this.searchResponseList : this.responseHistory
|
||||||
|
},
|
||||||
|
displayRequestLoading() {
|
||||||
|
return !!this.historySearchKeyword.trim() && this.historySearchLoading
|
||||||
|
},
|
||||||
|
displayResponseLoading() {
|
||||||
|
return !!this.historySearchKeyword.trim() && this.historySearchLoading
|
||||||
|
},
|
||||||
// 生成完整消息,用三个空行分隔
|
// 生成完整消息,用三个空行分隔
|
||||||
fullMessage() {
|
fullMessage() {
|
||||||
if (!this.resultList || this.resultList.length === 0) return ''
|
if (!this.resultList || this.resultList.length === 0) return ''
|
||||||
@@ -390,6 +425,48 @@ export default {
|
|||||||
this.$modal.msgError('加载历史记录失败')
|
this.$modal.msgError('加载历史记录失败')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 搜索框输入:防抖后请求后端在全部历史数据中搜索
|
||||||
|
onHistorySearchInput() {
|
||||||
|
if (this.historySearchTimer) clearTimeout(this.historySearchTimer)
|
||||||
|
const kw = (this.historySearchKeyword || '').trim()
|
||||||
|
if (!kw) {
|
||||||
|
this.searchRequestList = []
|
||||||
|
this.searchResponseList = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.historySearchTimer = setTimeout(() => {
|
||||||
|
this.loadHistorySearch(kw)
|
||||||
|
}, 300)
|
||||||
|
},
|
||||||
|
// 按关键词在全部数据中搜索(后端接口)
|
||||||
|
loadHistorySearch(keyword) {
|
||||||
|
if (!keyword || !keyword.trim()) {
|
||||||
|
this.searchRequestList = []
|
||||||
|
this.searchResponseList = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.historySearchLoading = true
|
||||||
|
const limit = 500
|
||||||
|
Promise.all([
|
||||||
|
getHistory('request', limit, keyword),
|
||||||
|
getHistory('response', limit, keyword)
|
||||||
|
]).then(([reqRes, respRes]) => {
|
||||||
|
this.historySearchLoading = false
|
||||||
|
if (reqRes && reqRes.code === 200) {
|
||||||
|
this.searchRequestList = reqRes.data || []
|
||||||
|
} else {
|
||||||
|
this.searchRequestList = []
|
||||||
|
}
|
||||||
|
if (respRes && respRes.code === 200) {
|
||||||
|
this.searchResponseList = respRes.data || []
|
||||||
|
} else {
|
||||||
|
this.searchResponseList = []
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.historySearchLoading = false
|
||||||
|
this.$modal.msgError('搜索历史记录失败')
|
||||||
|
})
|
||||||
|
},
|
||||||
extractTime(item) {
|
extractTime(item) {
|
||||||
if (!item) return ''
|
if (!item) return ''
|
||||||
const idx = item.indexOf(' | ')
|
const idx = item.indexOf(' | ')
|
||||||
@@ -811,6 +888,16 @@ export default {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.history-search-label {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-search-tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
/* 历史消息容器 */
|
/* 历史消息容器 */
|
||||||
.history-container {
|
.history-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user