|
@@ -1,109 +1,170 @@
|
|
|
<template>
|
|
|
- <div class="ranking-panel">
|
|
|
- <div class="panel-header">
|
|
|
- <el-select v-model="borrowType" placeholder="借用类型" style="width: 140px" @change="fetchRanking">
|
|
|
- <el-option label="全部" value="all" />
|
|
|
- <el-option label="常规借用" value="regular" />
|
|
|
- <el-option label="课堂借用" value="classroom" />
|
|
|
- <el-option label="特殊借用" value="special" />
|
|
|
- </el-select>
|
|
|
-
|
|
|
- <el-date-picker
|
|
|
- v-model="dateRange"
|
|
|
- type="daterange"
|
|
|
- start-placeholder="开始日期"
|
|
|
- end-placeholder="结束日期"
|
|
|
- style="margin-left: 10px"
|
|
|
- @change="fetchRanking"
|
|
|
- />
|
|
|
-
|
|
|
- <!-- <el-input
|
|
|
- v-model="keyword"
|
|
|
- placeholder="搜索用户/设备"
|
|
|
- clearable
|
|
|
- style="margin-left: 10px; width: 200px"
|
|
|
- /> -->
|
|
|
-
|
|
|
- <!-- <el-button type="primary" @click="fetchRanking" style="margin-left: 10px">
|
|
|
- 查询
|
|
|
- </el-button> -->
|
|
|
- </div>
|
|
|
-
|
|
|
- <el-table
|
|
|
- v-if="rankingData.length"
|
|
|
- :data="rankingData"
|
|
|
- style="width: 100%; margin-top: 20px"
|
|
|
- border
|
|
|
- >
|
|
|
- <el-table-column type="index" label="排名" width="60" />
|
|
|
- <el-table-column prop="device_name" label="设备名" />
|
|
|
- <el-table-column prop="device_code" label="设备编号" />
|
|
|
- <el-table-column prop="borrow_count" label="借用次数" />
|
|
|
- <!-- <el-table-column prop="total_quantity" label="累计借用册数" /> -->
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <div v-else class="empty-tip">暂无数据</div>
|
|
|
+ <div class="ranking-panel">
|
|
|
+ <div class="panel-title">
|
|
|
+ <div class="title">单台设备累计借用次数排名</div>
|
|
|
+ <!-- <div class="more">更多</div> -->
|
|
|
</div>
|
|
|
- </template>
|
|
|
-
|
|
|
- <script setup lang="ts">
|
|
|
- import { ref, onMounted } from 'vue'
|
|
|
- import * as api from '../api'
|
|
|
-
|
|
|
- interface RankingItem {
|
|
|
- user_id: number
|
|
|
- user_name: string
|
|
|
- user_code: string
|
|
|
- borrow_count: number
|
|
|
- total_quantity: number
|
|
|
+ <div class="panel-header">
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-select v-model="borrowType" clearable placeholder="借用类型" style="width: 140px;" @change="fetchRanking">
|
|
|
+ <el-option label="全部" value="all" />
|
|
|
+ <el-option label="常规借用" value="regular" />
|
|
|
+ <el-option label="课堂借用" value="classroom" />
|
|
|
+ <el-option label="特殊借用" value="special" />
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-date-picker v-model="dateRange" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" clearable
|
|
|
+ @change="fetchRanking" />
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-select clearable v-model="deviceTagId" placeholder="标签类型" style="margin-left: 30%; width: 140px;"
|
|
|
+ @change="fetchRanking">
|
|
|
+ <el-option v-for="item in labelType" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-table v-if="rankingData.length" :data="rankingData" style="width: 100%; margin-top: 20px; height: 350px"
|
|
|
+ max-height="500">
|
|
|
+ <el-table-column type="index" label="排名" width="60" />
|
|
|
+ <el-table-column prop="device_name" label="设备名" />
|
|
|
+ <el-table-column prop="device_name" label="标签名">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag v-for="tag in scope.row.device_tags" :key="tag" :type="tag.type">{{ tag.name }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="device_code" label="设备编号" />
|
|
|
+ <el-table-column prop="borrow_count" label="借用次数" />
|
|
|
+ <!-- <el-table-column prop="total_quantity" label="累计借用册数" /> -->
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <div v-else class="empty-tip">暂无数据</div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, onMounted } from 'vue'
|
|
|
+import * as api from '../api'
|
|
|
+import { GetList } from '../../devicelabel/api'
|
|
|
+
|
|
|
+interface RankingItem {
|
|
|
+ user_id: number
|
|
|
+ user_name: string
|
|
|
+ user_code: string
|
|
|
+ borrow_count: number
|
|
|
+ total_quantity: number
|
|
|
+}
|
|
|
+
|
|
|
+const borrowType = ref('all')
|
|
|
+const dateRange = ref<[string, string] | null>(null)
|
|
|
+const keyword = ref('')
|
|
|
+const rankingData = ref<RankingItem[]>([])
|
|
|
+const deviceTagId = ref('')
|
|
|
+
|
|
|
+const fetchRanking = async () => {
|
|
|
+ const params: Record<string, any> = {
|
|
|
+ type: borrowType.value
|
|
|
}
|
|
|
-
|
|
|
- const borrowType = ref('all')
|
|
|
- const dateRange = ref<[string, string] | null>(null)
|
|
|
- const keyword = ref('')
|
|
|
- const rankingData = ref<RankingItem[]>([])
|
|
|
-
|
|
|
- const fetchRanking = async () => {
|
|
|
- const params: Record<string, any> = {
|
|
|
- type: borrowType.value
|
|
|
- }
|
|
|
-
|
|
|
- if (dateRange.value) {
|
|
|
- params.start = dateRange.value[0]
|
|
|
- params.end = dateRange.value[1]
|
|
|
- }
|
|
|
-
|
|
|
- if (keyword.value) {
|
|
|
- params.keyword = keyword.value
|
|
|
- }
|
|
|
-
|
|
|
- const res = await api.GetBorrowRanking(params)
|
|
|
- if (res.code === 2000) {
|
|
|
- rankingData.value = res.data.borrow_count_ranking
|
|
|
- } else {
|
|
|
- rankingData.value = []
|
|
|
- }
|
|
|
+
|
|
|
+ if (dateRange.value) {
|
|
|
+ params.start = dateRange.value[0]
|
|
|
+ params.end = dateRange.value[1]
|
|
|
}
|
|
|
-
|
|
|
- onMounted(()=>{
|
|
|
- fetchRanking()
|
|
|
- })
|
|
|
- </script>
|
|
|
-
|
|
|
- <style scoped>
|
|
|
- .ranking-panel {
|
|
|
- width: 100%;
|
|
|
- padding: 10px;
|
|
|
+
|
|
|
+ if (keyword.value) {
|
|
|
+ params.keyword = keyword.value
|
|
|
}
|
|
|
- .panel-header {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- flex-wrap: wrap;
|
|
|
+ if (deviceTagId.value) {
|
|
|
+ params.tag_id = deviceTagId.value
|
|
|
}
|
|
|
- .empty-tip {
|
|
|
- text-align: center;
|
|
|
- color: #999;
|
|
|
- padding: 20px;
|
|
|
+ const res = await api.GetBorrowRanking(params)
|
|
|
+ if (res.code === 2000) {
|
|
|
+ rankingData.value = res.data.borrow_count_ranking
|
|
|
+ } else {
|
|
|
+ rankingData.value = []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const labelType = ref([])
|
|
|
+const getList = async () => {
|
|
|
+ const res = await GetList({
|
|
|
+ page: 1,
|
|
|
+ page_size: 20,
|
|
|
+ })
|
|
|
+ if (res.code === 2000) {
|
|
|
+ labelType.value = res.data
|
|
|
}
|
|
|
- </style>
|
|
|
-
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ fetchRanking()
|
|
|
+ getList()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.ranking-panel {
|
|
|
+ width: 100%;
|
|
|
+ padding: 16px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.panel-title {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.panel-title .title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+
|
|
|
+.panel-title .more {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #999;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.panel-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-tip {
|
|
|
+ text-align: center;
|
|
|
+ color: #999;
|
|
|
+ padding: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-table) {
|
|
|
+ border: none !important;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-table th) {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ color: #606266;
|
|
|
+ font-weight: 400;
|
|
|
+ border-bottom: 1px solid #EBEEF5;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-table td) {
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-table--border) {
|
|
|
+ border: none;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-table__inner-wrapper::before) {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+</style>
|