mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-18 01:06:39 +08:00
feat(ui):看板图表 样式调整
This commit is contained in:
parent
cbbcd4c571
commit
20915038a3
@ -14,6 +14,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@arco-design/web-vue": "^2.54.6",
|
"@arco-design/web-vue": "^2.54.6",
|
||||||
"@gpt-vue/packages": "workspace:^1.0.0",
|
"@gpt-vue/packages": "workspace:^1.0.0",
|
||||||
|
"echarts": "^5.5.0",
|
||||||
"md-editor-v3": "^2.2.1",
|
"md-editor-v3": "^2.2.1",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"vue": "^3.4.15",
|
"vue": "^3.4.15",
|
||||||
|
@ -80,8 +80,8 @@ const optionsEvent = {
|
|||||||
</slot>
|
</slot>
|
||||||
</AFormItem>
|
</AFormItem>
|
||||||
</AGridItem>
|
</AGridItem>
|
||||||
<AGridItem suffix>
|
<AGridItem>
|
||||||
<ASpace class="flex-end">
|
<ASpace>
|
||||||
<slot name="search-options" :option="optionsEvent">
|
<slot name="search-options" :option="optionsEvent">
|
||||||
<AButton type="primary" html-type="submit" :size="size" :loading="submitting">
|
<AButton type="primary" html-type="submit" :size="size" :loading="submitting">
|
||||||
<icon-search />
|
<icon-search />
|
||||||
@ -92,6 +92,10 @@ const optionsEvent = {
|
|||||||
<span>重置</span>
|
<span>重置</span>
|
||||||
</AButton>
|
</AButton>
|
||||||
</slot>
|
</slot>
|
||||||
|
</ASpace>
|
||||||
|
</AGridItem>
|
||||||
|
<AGridItem suffix>
|
||||||
|
<ASpace class="flex-end">
|
||||||
<slot name="search-extra" />
|
<slot name="search-extra" />
|
||||||
</ASpace>
|
</ASpace>
|
||||||
</AGridItem>
|
</AGridItem>
|
||||||
@ -100,7 +104,7 @@ const optionsEvent = {
|
|||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.search-form-conteiner {
|
.search-form-conteiner {
|
||||||
padding: 16px 0;
|
padding: 8px 0px 0px;
|
||||||
}
|
}
|
||||||
.flex-end {
|
.flex-end {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -33,12 +33,12 @@ const handleSearch = async (tips?: boolean) => {
|
|||||||
onActivated(handleSearch);
|
onActivated(handleSearch);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="simple-header">
|
|
||||||
<a-space>
|
|
||||||
<slot name="header" v-bind="{ reload: handleSearch }" />
|
|
||||||
</a-space>
|
|
||||||
</div>
|
|
||||||
<div class="simple-table">
|
<div class="simple-table">
|
||||||
|
<div class="simple-header">
|
||||||
|
<a-space class="flex-end">
|
||||||
|
<slot name="header" v-bind="{ reload: handleSearch }" />
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
<div ref="tableContainerRef" class="simple-table-container">
|
<div ref="tableContainerRef" class="simple-table-container">
|
||||||
<ATable
|
<ATable
|
||||||
v-bind="{
|
v-bind="{
|
||||||
@ -46,7 +46,7 @@ onActivated(handleSearch);
|
|||||||
...tableConfig,
|
...tableConfig,
|
||||||
...props,
|
...props,
|
||||||
scroll: useTableScroll(_columns || [], tableContainerRef as HTMLElement),
|
scroll: useTableScroll(_columns || [], tableContainerRef as HTMLElement),
|
||||||
columns: _columns
|
columns: _columns,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template v-for="slot in Object.keys($slots)" #[slot]="config">
|
<template v-for="slot in Object.keys($slots)" #[slot]="config">
|
||||||
@ -71,6 +71,10 @@ onActivated(handleSearch);
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.simple-header {
|
.simple-header {
|
||||||
padding: 16px 0;
|
padding: 8px 0px 16px;
|
||||||
|
}
|
||||||
|
.flex-end {
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -96,7 +96,9 @@ const handleStatusChange = ({ filed, value, record, reload }) => {
|
|||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
<template #header="{ reload }">
|
<template #header="{ reload }">
|
||||||
<a-button @click="popup({ reload })" size="small"><icon-plus />新增</a-button>
|
<a-button @click="popup({ reload })" size="small" type="primary"
|
||||||
|
><template #icon> <icon-plus /> </template>新增
|
||||||
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template #status="{ record, reload }">
|
<template #status="{ record, reload }">
|
||||||
<a-switch
|
<a-switch
|
||||||
|
@ -96,7 +96,9 @@ const handleStatusChange = ({ filed, value, record, reload }) => {
|
|||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
<template #header="{ reload }">
|
<template #header="{ reload }">
|
||||||
<a-button @click="popup({ reload })" size="small"><icon-plus />新增</a-button>
|
<a-button @click="popup({ reload })" size="small" type="primary"
|
||||||
|
><template #icon> <icon-plus /> </template>新增</a-button
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
<template #status="{ record, reload }">
|
<template #status="{ record, reload }">
|
||||||
<a-switch
|
<a-switch
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import http from "@/http/config";
|
import http from "@/http/config";
|
||||||
import { ref } from "vue";
|
import { ref, nextTick } from "vue";
|
||||||
|
import * as echarts from "echarts/core";
|
||||||
const dataSet = {
|
import { GridComponent, TitleComponent } from "echarts/components";
|
||||||
users: "今日新增用户",
|
import { LineChart } from "echarts/charts";
|
||||||
chats: "今日新增对话",
|
import { UniversalTransition } from "echarts/features";
|
||||||
tokens: "今日消耗 Tokens",
|
import { CanvasRenderer } from "echarts/renderers";
|
||||||
income: "今日入账",
|
|
||||||
};
|
|
||||||
|
|
||||||
const icons = {
|
const icons = {
|
||||||
users: "icon-user",
|
users: "icon-user",
|
||||||
@ -15,24 +13,81 @@ const icons = {
|
|||||||
tokens: "icon-computer",
|
tokens: "icon-computer",
|
||||||
income: "icon-wechatpay",
|
income: "icon-wechatpay",
|
||||||
};
|
};
|
||||||
|
const dataSet = {
|
||||||
|
users: "今日新增用户",
|
||||||
|
chats: "今日新增对话",
|
||||||
|
tokens: "今日消耗 Tokens",
|
||||||
|
income: "今日入账",
|
||||||
|
};
|
||||||
|
|
||||||
const data = ref<Record<string, number>>({});
|
|
||||||
const getData = () => {
|
const getData = () => {
|
||||||
http({
|
http({
|
||||||
url: "api/admin/dashboard/stats",
|
url: "api/admin/dashboard/stats",
|
||||||
method: "get",
|
method: "get",
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
data.value = res.data;
|
data.value = res.data;
|
||||||
|
handeChartData(res.data.chart);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
getData();
|
getData();
|
||||||
|
// 图表
|
||||||
|
const chartTitle = {
|
||||||
|
historyMessage: "对话",
|
||||||
|
orders: "订单",
|
||||||
|
users: "用户数",
|
||||||
|
};
|
||||||
|
echarts.use([GridComponent, LineChart, CanvasRenderer, UniversalTransition, TitleComponent]);
|
||||||
|
const chartDomRefs = [];
|
||||||
|
const chartData = ref({});
|
||||||
|
const data = ref<Record<string, number>>({});
|
||||||
|
const handeChartData = (data) => {
|
||||||
|
const _chartData = {};
|
||||||
|
for (let key in data) {
|
||||||
|
const type = data[key];
|
||||||
|
_chartData[key] = {
|
||||||
|
series: [],
|
||||||
|
xAxis: [],
|
||||||
|
};
|
||||||
|
for (let date in type) {
|
||||||
|
_chartData[key].series.push(type[date]);
|
||||||
|
_chartData[key].xAxis.push(date);
|
||||||
|
}
|
||||||
|
nextTick(() => {
|
||||||
|
const myChart = echarts.init(chartDomRefs.pop());
|
||||||
|
myChart.setOption(createOption(_chartData[key], key));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
chartData.value = _chartData;
|
||||||
|
};
|
||||||
|
const createOption = (data, key) => {
|
||||||
|
const { xAxis, series } = data;
|
||||||
|
return {
|
||||||
|
title: {
|
||||||
|
left: "center",
|
||||||
|
text: chartTitle[key],
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: xAxis,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value",
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: series,
|
||||||
|
type: "line",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="dashboard">
|
<div class="dashboard">
|
||||||
<a-grid :cols="{ xs: 1, sm: 1, md: 2, lg: 3, xl: 4 }" :colGap="12" :rowGap="16" class="grid">
|
<a-grid :cols="{ xs: 1, sm: 1, md: 2, lg: 3, xl: 4 }" :colGap="12" :rowGap="16" class="grid">
|
||||||
<a-grid-item v-for="(value, key) in dataSet" :key="key">
|
<a-grid-item v-for="(value, key) in dataSet" :key="key">
|
||||||
<div class="data-card">
|
<div class="data-card">
|
||||||
<span :class="key" class="icon"><icon-user /></span>
|
<span :class="key" class="icon"><component :is="icons[key]" /> </span>
|
||||||
<span class="count"
|
<span class="count"
|
||||||
><a-statistic :extra="value" :value="data[key]" :precision="0"
|
><a-statistic :extra="value" :value="data[key]" :precision="0"
|
||||||
/></span>
|
/></span>
|
||||||
@ -40,6 +95,27 @@ getData();
|
|||||||
</a-grid-item>
|
</a-grid-item>
|
||||||
</a-grid>
|
</a-grid>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="chart">
|
||||||
|
<a-grid
|
||||||
|
:cols="{ xs: 1, sm: 1, md: 1, lg: 2, xl: 2, xxl: 3 }"
|
||||||
|
:colGap="12"
|
||||||
|
:rowGap="16"
|
||||||
|
class="grid"
|
||||||
|
>
|
||||||
|
<a-grid-item v-for="(value, key, index) in chartData" :key="key">
|
||||||
|
<div
|
||||||
|
:ref="
|
||||||
|
(el) => {
|
||||||
|
chartDomRefs[index] = el;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
class="chartDom"
|
||||||
|
>
|
||||||
|
{{ key }}
|
||||||
|
</div>
|
||||||
|
</a-grid-item>
|
||||||
|
</a-grid>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.dashboard {
|
.dashboard {
|
||||||
@ -80,7 +156,15 @@ getData();
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
background: #f3f3f3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.chart {
|
||||||
|
margin-top: 15px;
|
||||||
|
.chartDom {
|
||||||
|
width: 450px;
|
||||||
|
height: 500px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -57,7 +57,7 @@ const handleRemove = async (id, reload) => {
|
|||||||
<template>
|
<template>
|
||||||
<SimpleTable :request="getList" :columns="columns" :pagination="false">
|
<SimpleTable :request="getList" :columns="columns" :pagination="false">
|
||||||
<template #header="{ reload }">
|
<template #header="{ reload }">
|
||||||
<a-button @click="openFormModal(reload, {})">
|
<a-button type="primary" @click="openFormModal(reload, {})">
|
||||||
<template #icon> <icon-plus /> </template>
|
<template #icon> <icon-plus /> </template>
|
||||||
新增
|
新增
|
||||||
</a-button>
|
</a-button>
|
||||||
|
@ -102,7 +102,9 @@ const handleStatusChange = ({ value, record, reload }) => {
|
|||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
<template #header="{ reload }">
|
<template #header="{ reload }">
|
||||||
<a-button @click="popup({ reload })" size="small"><icon-plus />新增</a-button>
|
<a-button @click="popup({ reload })" size="small" type="primary"
|
||||||
|
><template #icon> <icon-plus /> </template>新增
|
||||||
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template #status="{ record, reload }">
|
<template #status="{ record, reload }">
|
||||||
<a-switch
|
<a-switch
|
||||||
|
@ -105,7 +105,9 @@ const handleStatusChange = ({ value, record, reload }) => {
|
|||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
<template #header="{ reload }">
|
<template #header="{ reload }">
|
||||||
<a-button @click="popup({ reload })" size="small"><icon-plus />新增</a-button>
|
<a-button @click="popup({ reload })" size="small" type="primary"
|
||||||
|
><template #icon> <icon-plus /> </template>新增</a-button
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
<template #status="{ record, reload }">
|
<template #status="{ record, reload }">
|
||||||
<a-switch
|
<a-switch
|
||||||
|
@ -80,9 +80,9 @@ const handleDelete = async ({ id }: { id: string }, reload) => {
|
|||||||
<a-link @click="password({ record, reload })">重置密码</a-link>
|
<a-link @click="password({ record, reload })">重置密码</a-link>
|
||||||
</template>
|
</template>
|
||||||
<template #search-extra="{ reload }">
|
<template #search-extra="{ reload }">
|
||||||
<a-button @click="editModal({ reload })" status="success" size="small"
|
<a-button @click="editModal({ reload })" size="small" type="primary">
|
||||||
><icon-plus />新增用户</a-button
|
<template #icon> <icon-plus /> </template>新增
|
||||||
>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
</SearchTable>
|
</SearchTable>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user