parent
373d8b771b
commit
1285218eea
|
@ -0,0 +1,23 @@
|
|||
|
||||
|
||||
|
||||
import request from '@/config/axios'
|
||||
|
||||
export function page(params: any) {
|
||||
return request.get({
|
||||
url: '/chat/aigc/conversation/page',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function del(id: string) {
|
||||
return request.delete({
|
||||
url: `/chat/aigc/conversation/${id}`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getMessages(conversationId: string) {
|
||||
return request.get({
|
||||
url: `/chat/aigc/conversation/messages/${conversationId}`,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
|
||||
|
||||
import request from '@/config/axios'
|
||||
|
||||
/**
|
||||
* 消息列表接口参数
|
||||
*/
|
||||
export interface MessageParams {
|
||||
text?: string;
|
||||
username?: string;
|
||||
role?: string;
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取消息列表
|
||||
*/
|
||||
export function list(params: MessageParams) {
|
||||
return request.get({
|
||||
url: '/chat/aigc/message/list',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取消息列表
|
||||
*/
|
||||
export function page(params: MessageParams) {
|
||||
return request.get({
|
||||
url: '/chat/aigc/message/page',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加消息
|
||||
*/
|
||||
export function add(data: any) {
|
||||
return request.post({
|
||||
url: '/chat/aigc/message',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新消息
|
||||
*/
|
||||
export function update(data: any) {
|
||||
return request.put({
|
||||
url: '/chat/aigc/message',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除消息
|
||||
*/
|
||||
export function del(id: string) {
|
||||
return request.delete({
|
||||
url: `/chat/aigc/message/${id}`
|
||||
})
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
|
||||
import request from '@/config/axios'
|
||||
|
||||
export function getReqChartBy30() {
|
||||
return request.get({
|
||||
url: `/chat/aigc/statistic/requestBy30`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getReqChart() {
|
||||
return request.get({
|
||||
url: `/chat/aigc/statistic/request`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getTokenChartBy30() {
|
||||
return request.get({
|
||||
url: `/chat/aigc/statistic/tokenBy30`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getTokenChart() {
|
||||
return request.get({
|
||||
url: `/chat/aigc/statistic/token`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getHomeData() {
|
||||
return request.get({
|
||||
url: `/chat/aigc/statistic/home`,
|
||||
});
|
||||
}
|
|
@ -1,18 +1,4 @@
|
|||
<!--
|
||||
- Copyright (c) 2024 LangChat. TyCoding All Rights Reserved.
|
||||
-
|
||||
- Licensed under the GNU Affero General Public License, Version 3 (the "License");
|
||||
- you may not use this file except in compliance with the License.
|
||||
- You may obtain a copy of the License at
|
||||
-
|
||||
- https://www.gnu.org/licenses/agpl-3.0.html
|
||||
-
|
||||
- Unless required by applicable law or agreed to in writing, software
|
||||
- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
- See the License for the specific language governing permissions and
|
||||
- limitations under the License.
|
||||
-->
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue'
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
|
||||
|
||||
import { TableColumnCtx } from 'element-plus';
|
||||
import { ElTag } from 'element-plus';
|
||||
import { h } from 'vue';
|
||||
import type { FormSchema } from '@/types/form';
|
||||
export const columns: Partial<TableColumnCtx<any>>[] = [
|
||||
{
|
||||
label: '用户名',
|
||||
prop: 'username',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
label: '请求ip',
|
||||
prop: 'ip',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
label: '对话角色',
|
||||
prop: 'role',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
formatter: (row: any) => {
|
||||
return h(
|
||||
ElTag,
|
||||
{
|
||||
type: row.role === 'user' ? 'success' : 'danger',
|
||||
size: 'small',
|
||||
},
|
||||
{ default: () => row.role }
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '模型名称',
|
||||
prop: 'model',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
label: 'Token消耗',
|
||||
prop: 'tokens',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
label: '提示词Token消耗',
|
||||
prop: 'promptTokens',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
label: '消息内容',
|
||||
prop: 'message',
|
||||
formatter: (row: any) => {
|
||||
return String(row.message).replace(/```|\n/g, '');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '会话时间',
|
||||
prop: 'createTime',
|
||||
width: 180,
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
export const searchSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'text',
|
||||
component: 'Input',
|
||||
label: '内容',
|
||||
componentProps: {
|
||||
placeholder: '请输入内容查询',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'username',
|
||||
component: 'Input',
|
||||
label: '用户名',
|
||||
componentProps: {
|
||||
placeholder: '请输入用户名查询',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'role',
|
||||
component: 'Select',
|
||||
label: '对话角色',
|
||||
componentProps: {
|
||||
placeholder: '请选择对话角色查询',
|
||||
style: {
|
||||
width: '140px',
|
||||
},
|
||||
options: [
|
||||
{
|
||||
label: 'user',
|
||||
value: 'user',
|
||||
},
|
||||
{
|
||||
label: 'assistant',
|
||||
value: 'assistant',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
|
@ -0,0 +1,165 @@
|
|||
import { ref, computed } from 'vue'
|
||||
import type { FormSchema } from '@/types/form'
|
||||
import type { TableColumn } from '@/types/table'
|
||||
import { useTable } from '@/hooks/web/useTable'
|
||||
import { ElTag, dayjs } from 'element-plus'
|
||||
import { h } from 'vue'
|
||||
import * as MessageApi from '@/api/new-ai/message'
|
||||
|
||||
export default function () {
|
||||
const searchParams = ref({})
|
||||
|
||||
const schema = ref<FormSchema[]>([
|
||||
{
|
||||
field: 'text',
|
||||
component: 'Input',
|
||||
label: '内容',
|
||||
componentProps: {
|
||||
placeholder: '请输入内容查询'
|
||||
},
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'username',
|
||||
component: 'Input',
|
||||
label: '用户名',
|
||||
componentProps: {
|
||||
placeholder: '请输入用户名查询'
|
||||
},
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'role',
|
||||
component: 'Select',
|
||||
label: '对话角色',
|
||||
componentProps: {
|
||||
placeholder: '请选择对话角色查询',
|
||||
options: [
|
||||
{
|
||||
label: 'user',
|
||||
value: 'user'
|
||||
},
|
||||
{
|
||||
label: 'assistant',
|
||||
value: 'assistant'
|
||||
}
|
||||
]
|
||||
},
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
const columns = ref<TableColumn[]>([
|
||||
{
|
||||
label: '用户名',
|
||||
field: 'username',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
label: '请求ip',
|
||||
field: 'ip',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
label: '对话角色',
|
||||
field: 'role',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
formatter(row) {
|
||||
return h(
|
||||
ElTag,
|
||||
{
|
||||
type: row.role === 'user' ? 'success' : 'danger',
|
||||
size: 'small'
|
||||
},
|
||||
{
|
||||
default: () => row.role
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '模型名称',
|
||||
field: 'model',
|
||||
align: 'center',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
label: 'Token消耗',
|
||||
field: 'tokens',
|
||||
align: 'center',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
label: '提示词Token消耗',
|
||||
field: 'promptTokens',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
label: '消息内容',
|
||||
field: 'message',
|
||||
formatter: (row: any) => {
|
||||
return String(row.message).replace(/```|\n/g, '')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '会话时间',
|
||||
field: 'createTime',
|
||||
width: 180,
|
||||
align: 'center',
|
||||
formatter: (row: any) => {
|
||||
return dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
},
|
||||
|
||||
])
|
||||
|
||||
const { register, tableObject, methods } = useTable({
|
||||
getListApi: MessageApi.page,
|
||||
defaultParams: searchParams.value,
|
||||
delListApi: MessageApi.del
|
||||
})
|
||||
|
||||
const handleSearch = (values: any) => {
|
||||
methods.setSearchParams(values)
|
||||
// methods.getList()
|
||||
}
|
||||
|
||||
const pagination = computed(() => {
|
||||
return {
|
||||
total: tableObject.total,
|
||||
pageSize: tableObject.pageSize,
|
||||
currentPage: tableObject.currentPage
|
||||
}
|
||||
})
|
||||
|
||||
const handleDel = async (id: string | number) => {
|
||||
try {
|
||||
await methods.delList(id, false)
|
||||
} catch (error) {
|
||||
console.error('Failed to delete message:', error)
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
methods.getList()
|
||||
})
|
||||
return {
|
||||
schema,
|
||||
columns,
|
||||
register,
|
||||
handleSearch,
|
||||
methods,
|
||||
tableObject,
|
||||
pagination,
|
||||
handleDel
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import type { FormSchema } from '@/types/form'
|
||||
|
||||
export const searchSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'text',
|
||||
component: 'Input',
|
||||
label: '内容',
|
||||
componentProps: {
|
||||
placeholder: '请输入内容'
|
||||
}
|
||||
}
|
||||
]
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, ref } from 'vue';
|
||||
import { getMessages } from '@/api/new-ai/conversation';
|
||||
import Message from '@/views/ai/chat/new-chat/message/Message.vue';
|
||||
|
||||
const messageRef = ref();
|
||||
const contentRef = ref();
|
||||
const loading = ref(true);
|
||||
const dialogVisible = ref(false);
|
||||
const info = ref<any>({});
|
||||
const messages = ref<any>([]);
|
||||
|
||||
async function show(row: any) {
|
||||
dialogVisible.value = true;
|
||||
await nextTick();
|
||||
|
||||
info.value = row;
|
||||
messages.value = await getMessages(row.id);
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
async function handleDelete(row) {
|
||||
console.log('del', row);
|
||||
}
|
||||
|
||||
defineExpose({ show });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="dialogVisible"
|
||||
:title="info.title"
|
||||
size="1000px"
|
||||
direction="rtl"
|
||||
>
|
||||
<template #default>
|
||||
<div ref="contentRef" class="drawer-content">
|
||||
<el-scrollbar ref="messageRef" height="calc(100vh - 180px)">
|
||||
<Message
|
||||
v-for="(item, index) of messages"
|
||||
:key="index"
|
||||
:date-time="item.createTime"
|
||||
:error="false"
|
||||
:inversion="item.role !== 'assistant'"
|
||||
:loading="loading"
|
||||
:text="item.message"
|
||||
@delete="handleDelete(item)"
|
||||
/>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<el-empty v-if="messages.length === 0" description="此会话还没有聊天信息" class="mt-5" />
|
||||
</template>
|
||||
<template #footer>
|
||||
<div style="flex: auto">
|
||||
<el-button @click="dialogVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.drawer-content {
|
||||
height: 100%;
|
||||
padding: 0 20px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,107 @@
|
|||
import { ref, computed, onMounted } from 'vue'
|
||||
import type { FormSchema } from '@/types/form'
|
||||
import type { TableColumn } from '@/types/table'
|
||||
import { useTable } from '@/hooks/web/useTable'
|
||||
import { ElTag, dayjs } from 'element-plus'
|
||||
import { h } from 'vue'
|
||||
import * as ConversationApi from '@/api/new-ai/conversation'
|
||||
|
||||
export default function () {
|
||||
const searchParams = ref({})
|
||||
const infoRef = ref()
|
||||
|
||||
const schema = ref<FormSchema[]>([
|
||||
{
|
||||
field: 'text',
|
||||
component: 'Input',
|
||||
label: '内容',
|
||||
componentProps: {
|
||||
placeholder: '请输入内容'
|
||||
},
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
const columns = ref<TableColumn[]>([
|
||||
{
|
||||
label: '用户名',
|
||||
field: 'username',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
label: '窗口标题',
|
||||
field: 'title',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
label: '对话次数',
|
||||
field: 'chatTotal',
|
||||
align: 'center',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
label: 'Token消耗量',
|
||||
field: 'tokenUsed',
|
||||
align: 'center',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
label: '最后一次对话时间',
|
||||
field: 'endTime',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
formatter: (row: any) => {
|
||||
return dayjs(row.endTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
field: 'createTime',
|
||||
width: 180,
|
||||
align: 'center',
|
||||
formatter: (row: any) => {
|
||||
return dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
const { register, tableObject, methods } = useTable({
|
||||
getListApi: ConversationApi.page,
|
||||
defaultParams: searchParams.value,
|
||||
delListApi: ConversationApi.del
|
||||
})
|
||||
|
||||
const handleSearch = (values: any) => {
|
||||
methods.setSearchParams(values)
|
||||
}
|
||||
|
||||
const pagination = computed(() => {
|
||||
return {
|
||||
total: tableObject.total,
|
||||
pageSize: tableObject.pageSize,
|
||||
currentPage: tableObject.currentPage
|
||||
}
|
||||
})
|
||||
|
||||
const handleShowInfo = (row: any) => {
|
||||
infoRef.value?.show(row)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
methods.getList()
|
||||
})
|
||||
|
||||
return {
|
||||
schema,
|
||||
columns,
|
||||
register,
|
||||
handleSearch,
|
||||
methods,
|
||||
tableObject,
|
||||
pagination,
|
||||
handleShowInfo,
|
||||
infoRef
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Delete, View } from '@element-plus/icons-vue'
|
||||
import { Table } from '@/components/Table'
|
||||
import useConversation from './composables'
|
||||
import InfoList from './components/InfoList.vue'
|
||||
import { searchSchemas } from './columns'
|
||||
|
||||
const {
|
||||
columns,
|
||||
register,
|
||||
handleSearch,
|
||||
methods,
|
||||
tableObject,
|
||||
pagination,
|
||||
handleShowInfo,
|
||||
infoRef
|
||||
} = useConversation()
|
||||
|
||||
const actionColumn = {
|
||||
label: '操作',
|
||||
field: 'action',
|
||||
width: 80,
|
||||
fixed: 'right',
|
||||
align: 'center'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-2">
|
||||
<Search :schema="searchSchemas" inline @search="handleSearch" />
|
||||
|
||||
<Table :columns="[...columns, actionColumn]" :data="tableObject.tableList" :pagination="pagination" @register="register">
|
||||
<template #action="{ row }">
|
||||
<el-button :icon="View" text type="primary" @click="handleShowInfo(row)" />
|
||||
<el-button :icon="Delete" text type="danger" @click="methods.delList(row.id, false)" />
|
||||
</template>
|
||||
</Table>
|
||||
|
||||
<InfoList ref="infoRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { Delete } from '@element-plus/icons-vue'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import { Table } from '@/components/Table'
|
||||
import useMessage from './composables'
|
||||
import ConversationList from './conversation/index.vue'
|
||||
import { searchSchemas } from './columns'
|
||||
import { format } from 'path'
|
||||
const activeName = ref('1')
|
||||
const {
|
||||
schema,
|
||||
columns,
|
||||
register,
|
||||
handleSearch,
|
||||
methods,
|
||||
tableObject,
|
||||
pagination,
|
||||
handleDel
|
||||
} = useMessage()
|
||||
|
||||
const actionColumn = {
|
||||
label: '操作',
|
||||
field: 'action',
|
||||
width: 70,
|
||||
fixed: 'right',
|
||||
align: 'center',
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card>
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="会话消息列表" name="1">
|
||||
<div class="mt-2">
|
||||
<Search :schema="searchSchemas" @search="handleSearch"/>
|
||||
<Table
|
||||
:columns="[...columns, actionColumn]"
|
||||
:data="tableObject.tableList"
|
||||
:pagination="pagination"
|
||||
@register="register"
|
||||
>
|
||||
<template #action="{row}">
|
||||
<el-button :icon="Delete" text type="danger" @click="methods.delList(row.id, false)" />
|
||||
</template>
|
||||
</Table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="会话窗口列表" name="2">
|
||||
<ConversationList />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -0,0 +1,79 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { Echart } from '@/components/Echart';
|
||||
import { getReqChartBy30 } from '@/api/new-ai/statictic';
|
||||
|
||||
const options = ref({});
|
||||
|
||||
onMounted(async () => {
|
||||
const data = await getReqChartBy30();
|
||||
const xData: any = [];
|
||||
const yData: any = [];
|
||||
data.forEach((i: any) => {
|
||||
xData.push(i.date);
|
||||
yData.push(i.tokens);
|
||||
});
|
||||
|
||||
options.value = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#019680',
|
||||
},
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: xData,
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
type: 'solid',
|
||||
color: 'rgba(226,226,226,0.5)',
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
splitNumber: 4,
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
splitArea: {
|
||||
show: true,
|
||||
areaStyle: {
|
||||
color: ['rgba(255,255,255,0.2)', 'rgba(226,226,226,0.2)'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
grid: { left: '1%', right: '1%', top: '2%', bottom: 0, containLabel: true },
|
||||
series: [
|
||||
{
|
||||
smooth: true,
|
||||
data: yData,
|
||||
type: 'line',
|
||||
areaStyle: {},
|
||||
itemStyle: {
|
||||
color: '#5ab1ef',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h3 class="my-2 mb-6 text-lg">近30天请求汇总</h3>
|
||||
<Echart :options="options" height="240px" />
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,53 @@
|
|||
<!--
|
||||
- Copyright (c) 2024 LangChat. TyCoding All Rights Reserved.
|
||||
-
|
||||
- Licensed under the GNU Affero General Public License, Version 3 (the "License");
|
||||
- you may not use this file except in compliance with the License.
|
||||
- You may obtain a copy of the License at
|
||||
-
|
||||
- https://www.gnu.org/licenses/agpl-3.0.html
|
||||
-
|
||||
- Unless required by applicable law or agreed to in writing, software
|
||||
- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
- See the License for the specific language governing permissions and
|
||||
- limitations under the License.
|
||||
-->
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Delete } from '@element-plus/icons-vue'
|
||||
|
||||
import { searchSchemas } from './columns'
|
||||
import useOrder from '../composables'
|
||||
import { columns } from './columns'
|
||||
const { register, handleSearch, methods, tableObject, pagination } = useOrder()
|
||||
|
||||
const actionColumn = {
|
||||
label: '操作',
|
||||
field: 'action',
|
||||
width: 70,
|
||||
fixed: 'right',
|
||||
align: 'center'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full">
|
||||
<el-card>
|
||||
<Search :schema="searchSchemas" inline @search="handleSearch" />
|
||||
|
||||
<Table
|
||||
:columns="[...columns, actionColumn]"
|
||||
:data="tableObject.tableList"
|
||||
:pagination="pagination"
|
||||
@register="register"
|
||||
>
|
||||
<template #action="{ row }">
|
||||
<el-button :icon="Delete" text type="danger" @click="methods.delList(row.id, false)" />
|
||||
</template>
|
||||
</Table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -0,0 +1,56 @@
|
|||
import type { FormSchema } from '@/types/form';
|
||||
|
||||
export const columns = [
|
||||
{
|
||||
label: '用户名',
|
||||
field: 'username',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
label: '模型名称',
|
||||
field: 'model',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
label: 'Tokens',
|
||||
field: 'tokens',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
label: 'Prompt Tokens',
|
||||
field: 'promptTokens',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
label: 'Prompt Tokens',
|
||||
field: 'promptTokens',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
label: 'IP地址',
|
||||
field: 'ip',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
label: '调用时间',
|
||||
field: 'createTime',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
},
|
||||
];
|
||||
|
||||
export const searchSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
label: '用户名',
|
||||
componentProps: {
|
||||
placeholder: '请输入用户名查询'
|
||||
},
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
]
|
|
@ -0,0 +1,39 @@
|
|||
import { ref, computed, onMounted } from 'vue'
|
||||
|
||||
import type { TableColumn } from '@/types/table'
|
||||
import { useTable } from '@/hooks/web/useTable'
|
||||
import { dayjs } from 'element-plus'
|
||||
import {page, del} from '@/api/new-ai/message'
|
||||
|
||||
export default function () {
|
||||
const searchParams = ref({})
|
||||
const { register, tableObject, methods } = useTable({
|
||||
getListApi:page,
|
||||
defaultParams: searchParams.value,
|
||||
delListApi:del
|
||||
})
|
||||
|
||||
const handleSearch = (values: any) => {
|
||||
methods.setSearchParams(values)
|
||||
}
|
||||
|
||||
const pagination = computed(() => {
|
||||
return {
|
||||
total: tableObject.total,
|
||||
pageSize: tableObject.pageSize,
|
||||
currentPage: tableObject.currentPage
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
methods.getList()
|
||||
})
|
||||
|
||||
return {
|
||||
register,
|
||||
handleSearch,
|
||||
methods,
|
||||
tableObject,
|
||||
pagination
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Chart from './components/Chart.vue';
|
||||
import List from './components/List.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="overflow-y-auto h-full">
|
||||
<el-card>
|
||||
<Chart />
|
||||
<List />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
|
@ -114,4 +114,4 @@ defineExpose({ show })
|
|||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
Loading…
Reference in New Issue