mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	feat: add chart for admin dashbord
This commit is contained in:
		@@ -7,11 +7,13 @@
 | 
			
		||||
* 功能优化:SD 绘画页面采用 websocket 替换 http 轮询机制,节省带宽
 | 
			
		||||
* 功能优化:移动端聊天页面图片支持预览和放大功能
 | 
			
		||||
* 功能优化:MJ 和 SD 页面数据分页加载,解决一次性加载太多数据导致页面卡顿的问题
 | 
			
		||||
* 功能优化:**前端不登录也可以预览功能,只有在发起操作的时候才需要登录**
 | 
			
		||||
* 功能优化:**PC端不登录也可以预览功能,只有在发起操作的时候才需要登录**
 | 
			
		||||
* 功能优化:控制台订单管理页面显示未支付订单,并提供订单删除功能
 | 
			
		||||
* 功能新增:支持H5支付
 | 
			
		||||
* 功能优化:支持数学公式的识别和美化输出
 | 
			
		||||
* 功能新增:新增算力消费日志功能
 | 
			
		||||
* 功能优化:整合 XXL-JOB 实现订单清理,每日算力派发,VIP 算力重置等任务
 | 
			
		||||
* 功能新增:管理后台新增7日内新增用户和新增订单统计
 | 
			
		||||
 | 
			
		||||
## v3.2.7
 | 
			
		||||
* 功能重构:采用 Vant 重构移动页面,新增 MidJourney 功能
 | 
			
		||||
 
 | 
			
		||||
@@ -163,7 +163,7 @@ func (e *XXLJobExecutor) ResetUserPower(cxt context.Context, param *xxl.RunReq)
 | 
			
		||||
				Mark:      types.PowerAdd,
 | 
			
		||||
				Balance:   user.Power,
 | 
			
		||||
				Model:     "系统赠送",
 | 
			
		||||
				Remark:    fmt.Sprintf("系统每日算力派发,今日额度:%d", config.VipMonthPower),
 | 
			
		||||
				Remark:    fmt.Sprintf("系统每日算力派发,今日额度:%d", config.DailyPower),
 | 
			
		||||
				CreatedAt: time.Now(),
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
    "clipboard": "^2.0.11",
 | 
			
		||||
    "compressorjs": "^1.2.1",
 | 
			
		||||
    "core-js": "^3.8.3",
 | 
			
		||||
    "echarts": "^5.5.0",
 | 
			
		||||
    "element-plus": "^2.3.0",
 | 
			
		||||
    "good-storage": "^1.1.1",
 | 
			
		||||
    "highlight.js": "^11.7.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -171,27 +171,6 @@
 | 
			
		||||
                <el-tab-pane label="文生图(可选)" name="image">
 | 
			
		||||
                  <div class="text">图生图:以某张图片为底稿参考来创作绘画,生成类似风格或类型图像,支持 PNG 和 JPG 格式图片;
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="param-line pt">
 | 
			
		||||
                    <el-form-item label="">
 | 
			
		||||
                      <template #default>
 | 
			
		||||
                        <div class="form-item-inner flex-row items-center">
 | 
			
		||||
                          <el-input v-model="params.img" size="small" placeholder="请输入图片地址或者上传图片"
 | 
			
		||||
                                    style="width: 300px;"/>
 | 
			
		||||
                          <el-icon @click="params.img = ''" title="清空图片">
 | 
			
		||||
                            <DeleteFilled/>
 | 
			
		||||
                          </el-icon>
 | 
			
		||||
                          <el-tooltip effect="light"
 | 
			
		||||
                                      content="垫图:以某张图片为底稿参考来创作绘画 <br/> 支持 PNG 和 JPG 格式图片"
 | 
			
		||||
                                      raw-content placement="right">
 | 
			
		||||
                            <el-icon>
 | 
			
		||||
                              <InfoFilled/>
 | 
			
		||||
                            </el-icon>
 | 
			
		||||
                          </el-tooltip>
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </template>
 | 
			
		||||
                    </el-form-item>
 | 
			
		||||
                  </div>
 | 
			
		||||
 | 
			
		||||
                  <div class="param-line">
 | 
			
		||||
                    <div class="img-inline">
 | 
			
		||||
                      <div class="img-list-box">
 | 
			
		||||
 
 | 
			
		||||
@@ -124,7 +124,33 @@ const fetchData = () => {
 | 
			
		||||
  .inner {
 | 
			
		||||
    padding 0 20px 20px 20px
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar {
 | 
			
		||||
      width: 8px; /* 滚动条宽度 */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 修改滚动条轨道的背景颜色 */
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar-track {
 | 
			
		||||
      background-color: #ffffff;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 修改滚动条的滑块颜色 */
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar-thumb {
 | 
			
		||||
      background-color: #cccccc;
 | 
			
		||||
      border-radius 8px
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 修改滚动条的滑块的悬停颜色 */
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar-thumb:hover {
 | 
			
		||||
      background-color: #999999;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .list-box {
 | 
			
		||||
      overflow-x hidden
 | 
			
		||||
      //overflow-y auto
 | 
			
		||||
 | 
			
		||||
      .handle-box {
 | 
			
		||||
        padding 20px 0
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -54,26 +54,136 @@
 | 
			
		||||
        </el-card>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <el-row class="mgb20" :gutter="20">
 | 
			
		||||
      <el-col :span="8">
 | 
			
		||||
        <div class="e-chart">
 | 
			
		||||
          <div id="chart-users" style="height: 400px"></div>
 | 
			
		||||
          <div class="title">最近7日用户注册</div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="8">
 | 
			
		||||
        <div class="e-chart">
 | 
			
		||||
          <div id="chart-tokens" style="height: 400px"></div>
 | 
			
		||||
          <div class="title">最近7日Token消耗</div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="8">
 | 
			
		||||
        <div class="e-chart">
 | 
			
		||||
          <div id="chart-income" style="height: 400px"></div>
 | 
			
		||||
          <div class="title">最近7日收入</div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {ref} from 'vue';
 | 
			
		||||
import {onMounted, ref} from 'vue';
 | 
			
		||||
import {ChatDotRound, TrendCharts, User} from "@element-plus/icons-vue";
 | 
			
		||||
import {httpGet} from "@/utils/http";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import * as echarts from 'echarts';
 | 
			
		||||
 | 
			
		||||
const stats = ref({users: 0, chats: 0, tokens: 0, rewards: 0})
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
 | 
			
		||||
httpGet('/api/admin/dashboard/stats').then((res) => {
 | 
			
		||||
  stats.value.users = res.data.users
 | 
			
		||||
  stats.value.chats = res.data.chats
 | 
			
		||||
  stats.value.tokens = res.data.tokens
 | 
			
		||||
  stats.value.income = res.data.income
 | 
			
		||||
  loading.value = false
 | 
			
		||||
}).catch((e) => {
 | 
			
		||||
  ElMessage.error("获取统计数据失败:" + e.message)
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  const chartUsers = echarts.init(document.getElementById("chart-users"))
 | 
			
		||||
  const chartTokens = echarts.init(document.getElementById("chart-tokens"))
 | 
			
		||||
  const chartIncome = echarts.init(document.getElementById("chart-income"))
 | 
			
		||||
  httpGet('/api/admin/dashboard/stats').then((res) => {
 | 
			
		||||
    stats.value.users = res.data.users
 | 
			
		||||
    stats.value.chats = res.data.chats
 | 
			
		||||
    stats.value.tokens = res.data.tokens
 | 
			
		||||
    stats.value.income = res.data.income
 | 
			
		||||
    const chartData = res.data.chart
 | 
			
		||||
    loading.value = false
 | 
			
		||||
 | 
			
		||||
    const x = []
 | 
			
		||||
    const dataUsers = []
 | 
			
		||||
    for (let k in chartData.users) {
 | 
			
		||||
      x.push(k)
 | 
			
		||||
      dataUsers.push(chartData.users[k])
 | 
			
		||||
    }
 | 
			
		||||
    chartUsers.setOption({
 | 
			
		||||
      xAxis: {
 | 
			
		||||
        data: x
 | 
			
		||||
      },
 | 
			
		||||
      yAxis: {},
 | 
			
		||||
      series: [
 | 
			
		||||
        {
 | 
			
		||||
          data: dataUsers,
 | 
			
		||||
          type: 'line',
 | 
			
		||||
          label: {
 | 
			
		||||
            show: true,
 | 
			
		||||
            position: 'bottom',
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              fontSize: 18
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    })
 | 
			
		||||
    const dataTokens = []
 | 
			
		||||
    for (let k in chartData.historyMessage) {
 | 
			
		||||
      dataTokens.push(chartData.historyMessage[k])
 | 
			
		||||
    }
 | 
			
		||||
    chartTokens.setOption({
 | 
			
		||||
      xAxis: {
 | 
			
		||||
        data: x
 | 
			
		||||
      },
 | 
			
		||||
      yAxis: {},
 | 
			
		||||
      series: [
 | 
			
		||||
        {
 | 
			
		||||
          data: dataTokens,
 | 
			
		||||
          type: 'line',
 | 
			
		||||
          label: {
 | 
			
		||||
            show: true,
 | 
			
		||||
            position: 'bottom',
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              fontSize: 18
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const dataIncome = []
 | 
			
		||||
    for (let k in chartData.orders) {
 | 
			
		||||
      dataIncome.push(chartData.orders[k])
 | 
			
		||||
    }
 | 
			
		||||
    chartIncome.setOption({
 | 
			
		||||
      xAxis: {
 | 
			
		||||
        data: x
 | 
			
		||||
      },
 | 
			
		||||
      yAxis: {},
 | 
			
		||||
      series: [
 | 
			
		||||
        {
 | 
			
		||||
          data: dataIncome,
 | 
			
		||||
          type: 'line',
 | 
			
		||||
          label: {
 | 
			
		||||
            show: true,
 | 
			
		||||
            position: 'bottom',
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              fontSize: 18
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
  }).catch((e) => {
 | 
			
		||||
    ElMessage.error("获取统计数据失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  window.onresize = function () { // 自适应大小
 | 
			
		||||
    chartUsers.resize()
 | 
			
		||||
    chartTokens.resize()
 | 
			
		||||
    chartIncome.resize()
 | 
			
		||||
  };
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
@@ -113,6 +223,14 @@ httpGet('/api/admin/dashboard/stats').then((res) => {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .e-chart {
 | 
			
		||||
    .title {
 | 
			
		||||
      text-align center
 | 
			
		||||
      font-size 16px
 | 
			
		||||
      color #444444
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .grid-con-1 .grid-con-icon {
 | 
			
		||||
    background: rgb(45, 140, 240);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user