Ai调用日志页面ui

This commit is contained in:
dong.ai
2025-09-24 14:57:37 +08:00
committed by joshen
parent 4d75fb03ee
commit bd8d877b93
2 changed files with 619 additions and 6 deletions

View File

@@ -36,3 +36,12 @@ export const caseRecommend = (data) => http.post('/xboe/m/boe/cases/recommend/la
export const userList = (data) => httpUserbase.post('/user/list', data)
//案例查询组织所有人数
export const getOrgUsers = (data) => httpUserbase.post('/user/getOrgUsers', data)
// AI调用日志列表查询
export const getAiLogList = (data) => http.post('/xboe/m/boe/caseDocumentLog/pageQuery', data)
// 清空日志
export const getClearLogs = (data) => http.post('/xboe/m/boe/caseDocumentLog/clearLogs', data)
// 重试
export const getRetry = (data) => http.post('/xboe/m/boe/caseDocumentLog/retry', data)

View File

@@ -0,0 +1,604 @@
<template>
<div class="researchmanage">
<!-- 搜索框及按钮 -->
<div class="filter">
<div class="filterItems">
<div class="select">
<span style="margin-right: 10px;">案例标题</span>
<a-input v-model:value="searchData.caseTitle" style="width: 270px; height: 40px; border-radius: 8px"
placeholder="请输入用户姓名" />
</div>
<div class="select">
<span style="margin-right: 10px;">操作类型</span>
<a-select v-model:value="searchData.optType" style="width: 270px" placeholder="请选择课程类型" allowClear>
<a-select-option value="create">新增</a-select-option>
<a-select-option value="update">更改</a-select-option>
<a-select-option value="delete">删除</a-select-option>
</a-select>
</div>
<div class="select">
<div class="select addTimeBox">
<span style="margin-right: 10px;">调用时间</span>
<a-range-picker v-model:value="searchData.callTimeList" style="width: 350px" format="YYYY-MM-DD"
valueFormat="YYYY-MM-DD" separator="至" :placeholder="[' 开始时间', ' 结束时间']" />
</div>
</div>
<div class="select">
<span style="margin-right: 10px;">接口调用结果</span>
<a-select v-model:value="searchData.optStatus" style="width: 270px" placeholder="请选择课程类型" allowClear>
<a-select-option value="1">成功</a-select-option>
<a-select-option value="2">失败</a-select-option>
</a-select>
</div>
<div class="select">
<span style="margin-right: 10px;">业务处理结果</span>
<a-select v-model:value="searchData.caseStatus" style="width: 270px" placeholder="请选择课程类型" allowClear>
<a-select-option value="1">成功</a-select-option>
<a-select-option value="2">失败</a-select-option>
</a-select>
</div>
<div style="display: flex; margin-bottom: 20px">
<div class="btn btn1" @click="handleSearch">
<div class="search"></div>
<div class="btnText">搜索</div>
</div>
<div class="btn btn2" @click="handleReset" style="width: 105px">
<div class="search"></div>
<div class="btnText">重置</div>
</div>
</div>
</div>
</div>
<!-- 搜索框及按钮 -->
<!-- 表格 -->
<div class="clear-btn">
<a-button type="primary" @click="handleClearLog" danger ghost>清空日志</a-button>
</div>
<div class="tableBox">
<a-table style="border: 1px solid #f2f6fe" :columns="column" :data-source="tableData" :loading="loading"
:scroll="{ x: 1100 }" :pagination="false">
<template #actions="{ text, record, index }">
<a-space :key="record.id">
<a-button @click="() => handleMark(record)" type="link">
查看
</a-button>
<a-button @click="() => handleRetry(record)" :disabled="record.caseStatus == 1 && record.optStatus == 1"
type="link">
重试
</a-button>
</a-space>
</template>
</a-table>
</div>
<div class="pa" style="display: flex; justify-content: flex-end; padding: 0 38px">
<a-pagination show-quick-jumper :pageSize="pageSize" :current="pageIndex" :total="total" class="pagination"
@change="handelChangePage" show-size-changer />
</div>
<a-modal v-model:visible="markShow" :footer="null" width="40%" title="查看详细报文">
<div class="markContent">
<p>{{ resContent }}</p>
<p>{{ reqContent }}</p>
</div>
</a-modal>
</div>
</template>
<script lang="jsx">
import { defineComponent, onMounted, reactive, toRefs } from "vue";
import dialog from "@/utils/dialog";
import { getAiLogList, getClearLogs, getRetry } from "@/api/case";
export default defineComponent({
setup() {
const state = reactive({
searchData: {
caseTitle: "",
optType: "",
optStatus: "",
caseStatus: "",
callTimeList: [],
},
markShow: false,
resContent: '',
reqContent: '',
total: 0,
pageIndex: 1,
pageSize: 10,
column: [
{
title: "案例标题",
dataIndex: "caseTitle",
key: "caseTitle",
width: "10%",
ellipsis: true,
className: "h",
customRender: ({ text }) => {
return text ? text : "-";
},
},
{
title: "操作类型",
dataIndex: "optType",
key: "optType",
width: "10%",
className: "h",
customRender: ({ text }) => {
switch (text) {
case 'create':
return <span>新增</ span>;
case 'delete':
return <span>删除</span>;
case 'update':
return <span>更改</span>;
default:
return <span>-</span>;
}
},
},
{
title: "调用接口",
dataIndex: "requestUrl",
key: "requestUrl",
width: "10%",
className: "h",
customRender: ({ text }) => {
return text ? text : "-";
},
},
{
title: "调用时间",
dataIndex: "callTime",
key: "callTime",
width: "15%",
className: "h",
customRender: ({ text }) => {
return text ? text : "-";
},
},
{
title: "请求参数",
dataIndex: "requestBody",
key: "requestBody",
width: "25%",
className: "h",
customRender: ({ text }) => {
return text ? text : "-";
},
},
{
title: "响应参数",
dataIndex: "responseBody",
key: "responseBody",
width: "25%",
className: "h",
customRender: ({ text }) => {
return text ? text : "-";
},
},
{
title: "接口调用结果",
dataIndex: "optStatus",
key: "optStatus",
width: "8%",
className: "h",
customRender: ({ text }) => {
switch (text) {
case 1:
return <span style={{ color: "#A5D161" }} >成功</ span>;
case 2:
return <span style={{ color: "#DB0F28" }}>失败</span>;
default:
return <span>-</span>;
}
},
},
{
title: "业务处理结果",
dataIndex: "caseStatus",
key: "caseStatus",
width: "8%",
className: "h",
customRender: ({ text }) => {
switch (text) {
case 1:
return <span style={{ color: "#A5D161" }} >成功</ span>;
case 2:
return <span style={{ color: "#DB0F28" }}>失败</span>;
default:
return <span>-</span>;
}
},
},
{
title: "操作",
width: "10%",
dataIndex: "id",
key: "id",
fixed: "right",
slots: { customRender: "actions" },
},
],
tableData: [
{
id: "log123",
taskId: "task456",
caseId: "case789",
caseTitle: "测试案例",
optType: "create",
requestUrl: "https://api.example.com/upload",
requestBody: "{\"fileId\":\"file123\"}",
responseBody: "{\"code\":0,\"message\":\"success\"}",
optTime: "2024-01-15 10:30:00",
optStatus: 1,
caseStatus: 1,
}
]
})
const getTableDate = async () => {
let res = await getAiLogList({
pageIndex: state.pageIndex,
pageSize: state.pageSize,
caseTitle: state.caseTitle,
optType: state.optType,
optStatus: state.optStatus,
caseStatus: state.caseStatus,
startTime: state.callTimeList[0],
endTime: state.callTimeList[1],
});
const { records, totalPages } = res.data.data.content;
const { count } = res.data.data
state.count = count
state.tableData = records;
state.total = totalPages;
}
getTableDate()
// 搜索
const handleSearch = () => {
state.currentPage1 = 1
// 在这里可以添加实际的搜索逻辑
console.log('搜索参数:', state.searchData)
getTableDate();
};
// 重置
const handleReset = () => {
state.searchData = {
pageIndex: 1,
pageSize: 10,
caseTitle: "",
optType: "",
optStatus: "",
caseStatus: "",
callTimeList: [],
};
getTableDate();
};
// 清空日志
function handleClearLog() {
dialog({ content: '确定清空当前日志吗?', ok: handleClearLogOk });
}
const handleClearLogOk = async () => {
try {
// 这里应该调用实际的API接口
let paramsData = {
caseTitle: state.caseTitle,
optType: state.optType,
optStatus: state.optStatus,
caseStatus: state.caseStatus,
startTime: state.callTimeList[0],
endTime: state.callTimeList[1],
};
let res = await getClearLogs(paramsData);
console.log(res, '清空日志接口返回参数');
// if (res.data.data.status == 200) {
// message.success(res.data.data.message);
// 重新加载数据
// getTableDate();
// } else {
// message.error(res.data.data.message);
// }
} catch (error) {
console.log(error);
}
}
// 查看
const handleMark = (record) => {
console.log(record);
state.markShow = true;
state.resContent = record.requestBody;
state.reqContent = record.responseBody;
}
// 重试
function handleRetry(record) {
dialog({ content: '确定重试当前失败请求吗?', ok: handleRetryOk(record) });
}
const handleRetryOk = async (record) => {
try {
let res = await getRetry({ logId: record.id });
console.log(res, '重试接口返回参数');
} catch (error) {
console.log(error);
}
}
//分页
const handelChangePage = (page, pageSize) => {
state.pageIndex = page;
state.pageSize = pageSize;
getTableDate();
};
onMounted(() => {
});
return {
...toRefs(state),
handleSearch,
handleReset,
handleMark,
handleClearLog,
handleRetry,
handelChangePage,
getTableDate
}
}
})
</script>
<style lang="scss">
.clearfix:before,
.clearfix:after {
content: " ";
display: block;
clear: both;
}
.addTimeBox {
position: relative;
display: flex;
align-items: center;
.addTime {
position: absolute;
z-index: 10;
margin-left: 10px;
color: rgba(0, 0, 0, 0.4);
}
.ant-picker {
padding-left: 35px;
}
// .ant-picker-range .ant-picker-active-bar {
// margin-left: 35px;
// }
}
.researchmanage {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
position: relative;
.filter {
margin-left: 38px;
margin-right: 38px;
margin-top: 30px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.filterItems {
display: flex;
flex-wrap: wrap;
.select {
margin-right: 20px;
margin-bottom: 20px;
}
.btn {
padding: 0 26px 0 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
background-size: 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 36px;
margin-left: 5px;
}
}
.btnn {
padding: 0 26px 0 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
border: 1px solid rgba(64, 158, 255, 1);
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
background-size: 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #fff;
line-height: 36px;
margin-left: 5px;
}
}
.btn1 {
.search {
width: 15px;
height: 17px;
background-image: url("../../assets/images/courseManage/search0.png");
}
}
.btn2 {
.search {
width: 16px;
height: 18px;
background-image: url("../../assets/images/courseManage/reset0.png");
}
}
.btn1:active {
background: #0982ff;
}
.btn2:active {
background: rgba(64, 158, 255, 0.2);
}
}
.btns {
display: flex;
.btn {
padding: 0 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
background-size: 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 36px;
margin-left: 5px;
}
}
.btn3 {
margin-right: 0;
.search {
width: 17px;
height: 18px;
background-image: url("../../assets/images/courseManage/add0.png");
}
}
.btn3:active {
background: #0982ff;
}
}
}
.tableBox {
margin: 20px 38px 30px;
display: flex;
flex: 1;
flex-direction: column;
th.ant-table-cell {
background-color: #eff4fc !important;
text-align: center;
color: #999ba3;
}
td.ant-table-cell {
text-align: center;
}
}
.pa {
width: 100%;
display: flex;
justify-content: center;
margin-bottom: 20px;
.pagination {
margin-bottom: 20px;
}
.ant-pagination-item-link,
.ant-pagination-item,
.ant-select-selector,
.ant-pagination-options-quick-jumper input {
border-radius: 8px;
}
}
.unout {
display: none;
}
.operation {
display: flex;
justify-content: right;
.fb {
display: flex;
margin-right: 20px;
.jc {
color: #4ea6ff;
font-size: 14px;
margin-left: 20px;
white-space: nowrap;
cursor: pointer;
}
}
}
}
.clear-btn {
display: flex;
justify-content: flex-end;
padding-right: 38px;
.ant-btn-background-ghost.ant-btn-dangerous {
border-radius: 5px;
}
}
.markContent {
padding: 20px;
min-height: 400px;
font-size: 16px;
p {
margin-bottom: 0;
}
}
</style>