From 086be7eae50e48ad554fd8a3f4cb1e333d587595 Mon Sep 17 00:00:00 2001
From: rk <94314517@qq.com>
Date: 星期二, 27 一月 2026 10:33:11 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
admin/src/views/index.vue | 611 +++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 523 insertions(+), 88 deletions(-)
diff --git a/admin/src/views/index.vue b/admin/src/views/index.vue
index 099186b..2cd5e29 100644
--- a/admin/src/views/index.vue
+++ b/admin/src/views/index.vue
@@ -1,93 +1,338 @@
<template>
<TableLayout>
<div slot="search-form" class="data">
- <div class="item-title">鏁版嵁鐪嬫澘</div>
+ <div class="top-tab">
+ <div class="tab-title">缁忚惀鏁版嵁鍒嗘瀽</div>
+ <div class="tab-item">
+ <span v-for="(item,index) in tabs" :key="'tab'+index" :class="item.index==tabIndex?'active-tab tab-btn':'tab-btn'" @click="changeTab(item)">{{item.name}}</span>
+ </div>
+ </div>
+ <div class="item-title"> </div>
<div class="data-summary">
- <div class="data-item">
- <div>浼氬憳鏁伴噺</div>
- <div class="data-num">{{ countData.users }}</div>
+ <div class="data-item blue">
+ <div>{{tabName}}閿�鍞</div>
+ <div class="data-num">锟{ (topData.price ||0).toFixed(2) }}</div>
</div>
<div class="parting"></div>
- <div class="data-item">
- <div>浠婃棩娲昏穬鐢ㄦ埛</div>
- <div class="data-num">{{ countData.activeUsers }}</div>
+ <div class="data-item yellow">
+ <div>{{tabName}}鎴愪氦璁㈠崟閲�</div>
+ <div class="data-num">{{ topData.num||0}}</div>
</div>
<div class="parting"></div>
- <div class="data-item">
- <div>璁㈠崟鎬绘暟</div>
- <div class="data-num">{{ countData.orders }}</div>
+ <div class="data-item green">
+ <div>{{tabName}}閫�娆鹃噾棰�</div>
+ <div class="data-num">锟{( topData.price1 ||0).toFixed(2) }}</div>
</div>
<div class="parting"></div>
- <div class="data-item">
- <div>璁㈠崟鎬婚噾棰�</div>
- <div class="data-num">{{ countData.money }}</div>
+ <div class="data-item orange">
+ <div>{{tabName}}閫�娆捐鍗曢噺</div>
+ <div class="data-num">{{ topData.num1 ||0 }}</div>
</div>
<div class="parting"></div>
- <div class="data-item">
- <div>鏈湀璁㈠崟鏁�</div>
- <div class="data-num">{{ countData.mouthOrders }}</div>
- </div>
- <div class="parting"></div>
- <div class="data-item">
- <div>鏈湀璁㈠崟鎬婚噾棰�</div>
- <div class="data-num">{{ countData.mouthMoney }}</div>
- </div>
</div>
</div>
<template v-slot:table-wrap>
<div class="change-style">
- <div class="item-title">璁㈠崟閲戦瓒嬪娍</div>
- <div style="display: flex;">
- <el-button type="text" @click="changeCount(7)">7鏃�</el-button>
- <div style="margin: 0 5px;">|</div>
- <el-button type="text" @click="changeCount(30)">30鏃�</el-button>
+ <div class="count-left">
+ <div class="item-title">璁㈠崟閲忎笌閿�鍞瓒嬪娍</div>
+ <div ref="orderCount" class="bottom" ></div>
+ </div>
+ <div class="count-right">
+ <div class="item-title">鍚勫搧绫婚攢鍞鍗犳瘮</div>
+ <div ref="cateCount" class="bottom"></div>
</div>
</div>
- <div ref="orderChange" class="bottom">
-
+ <div class="change-style">
+ <div class="tab-title" style="display: flex;align-items: center; ">
+ <span style="">鎺掑悕鍒嗘瀽</span>
+ <div class="tab-item" style="margin-left: 20px;" >
+ <el-date-picker style="width: 110px;height: 22px;margin-right: 10px;" v-model="searchForm.topYear" type="year" @change="changeYearMonth"
+ clearable value-format="yyyy" format="yyyy'骞�'" placeholder="骞翠唤" ></el-date-picker>
+ <el-date-picker style="width: 100px;height: 22px;" v-model="searchForm.topMonth" type="month" @change="changeYearMonth"
+ clearable value-format="MM" format="MM'鏈�'" placeholder="鏈堜唤" ></el-date-picker>
+ </div>
+ </div>
+ </div>
+ <div class="change-style">
+ <div class="count-left">
+ <div class="item-title" style="display: flex;">
+ <span style="flex: 1">缁忛攢鍟員OP10</span>
+ <div class="tab-item" style="text-align: right;flex: 1.5; ">
+ <span v-for="(item,index) in tabs1" :key="'tab'+index" :class="item.index==tabIndex1?'active-tab tab-btn':'tab-btn'" @click="changeTab1(item)">{{item.name}}</span>
+ </div>
+ </div>
+ <div class="bottom1">
+ <el-table :data="dataList1||[]" stripe border inline >
+ <el-table-column prop="sortnum" label="鎺掑悕" align="center">
+ <template slot-scope="scope">{{scope.$index +1}}</template>
+ </el-table-column>
+ <el-table-column prop="name" label="缁忛攢鍟嗗悕绉�" align="center" > </el-table-column>
+ <el-table-column prop="num" label="璁㈠崟閲�" align="center" > </el-table-column>
+ <el-table-column prop="price" label="閿�鍞锛堝厓锛�" align="center" ></el-table-column>
+ <el-table-column prop="num1" label="浼氬憳鏁�" align="center" ></el-table-column>
+ </el-table>
+ </div>
+ </div>
+ <div class="count-right">
+ <div class="item-title">
+ <div class="item-title" style="display: flex;">
+ <span style="flex: 1">鍗曚竴鍟嗗搧TOP10</span>
+ <div class="tab-item" style="text-align: right;flex: 1.5; ">
+ <span v-for="(item,index) in tabs2" :key="'tab'+index" :class="item.index==tabIndex2?'active-tab tab-btn':'tab-btn'" @click="changeTab2(item)">{{item.name}}</span>
+ </div>
+ </div>
+ </div>
+ <div class="bottom1">
+ <el-table :data="dataList2||[]" stripe border >
+ <el-table-column prop="sortnum" label="鎺掑悕" align="center">
+ <template slot-scope="scope">{{scope.$index +1}}</template>
+ </el-table-column>
+ <el-table-column prop="name" label="鍟嗗搧鍚嶇О" align="center" > </el-table-column>
+ <el-table-column prop="num" label="閿�閲�" align="center" > </el-table-column>
+ <el-table-column prop="price" label="閿�鍞锛堝厓锛�" align="center" ></el-table-column>
+ </el-table>
+ </div>
+ </div>
+ </div>
+ <div class="change-style">
+ <div class="tab-title" style="display: flex;align-items: center; ">
+ <span style="">钀ラ攢鏁版嵁鍒嗘瀽</span>
+ <div class="tab-item" style="margin-left: 20px;" >
+ <el-date-picker style="width: 110px;height: 22px;margin-right: 10px;" v-model="searchForm.topYear2" type="year" @change="changeYear"
+ clearable value-format="yyyy" format="yyyy'骞�'" placeholder="骞翠唤" ></el-date-picker>
+ </div>
+ </div>
+ </div>
+ <div class="change-style">
+ <div class="count-left">
+ <div class="item-title">绉垎鍙戞斁绫诲瀷鍗犳瘮</div>
+ <div class="bottom2" style="display: flex;align-items: center">
+ <div ref="integralCount" style="flex: 1;min-height: 200px;"></div>
+ <div style="flex: 1;font-size: 14px;font-weight: 500;margin-left: 20px;">
+ <div>绱鍙戞斁鏁伴噺锛歿{( dataList4.num || 0 ) +( dataList4.num1 || 0 )+( dataList4.num2 || 0 )+( dataList4.num3 || 0 )}}</div>
+ <div>绱娑堣�楋細{{ dataList4.useNum || 0 }}</div>
+ <div>绱浼樻儬閲戦锛氾骏{{(dataList4.price || 0 ).toFixed(2) }}</div>
+ </div>
+ </div>
+ </div>
+ <div class="count-right">
+ <div class="item-title">浼樻儬鍒稿彂鏀剧被鍨嬪崰姣�</div>
+ <div class="bottom2" style="display: flex;align-items: center">
+ <div ref="couponCount" style="flex: 1;min-height: 200px;"></div>
+ <div style="flex: 1;font-size: 14px;font-weight: 500;margin-left: 20px;">
+ <div>绱鍙戞斁鏁伴噺锛歿{( dataList3.num || 0 ) +( dataList3.num1 || 0 )}}</div>
+ <div>宸蹭娇鐢ㄤ紭鎯犲埜锛歿{ dataList3.useNum || 0 }}</div>
+ <div>绱浼樻儬閲戦锛氾骏{{(dataList3.price || 0 ).toFixed(2) }}</div>
+ <div>淇冩垚浜ゆ槗閲戦锛氾骏{{(dataList3.orderPrice || 0 ).toFixed(2) }}</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="change-style" v-if="1==2">
+ <div class="item-title">钀ラ攢鎶曞叆璐圭敤涓庨攢鍞鍒嗘瀽</div>
+ <div ref="feeCount" class="bottom"></div>
</div>
</template>
-
+
</TableLayout>
</template>
<script>
import TableLayout from '@/layouts/TableLayout'
-import * as echarts from 'echarts';
-import { findAllList, createCoffeeTask } from '@/api/business/taskRule'
+import BaseTable from '@/components/base/BaseTable'
+import * as echarts from 'echarts'
export default {
+ extends: BaseTable,
components: {
TableLayout
},
- data() {
+ data () {
return {
- countData: {
- users: 1000,
- activeUsers: 1000,
- mouthOrders: 10,
- mouthMoney: 100000,
- orders: 10,
- money: 100000
+ loading1: false,
+ loading2: false,
+ loading3: false,
+ loading4: false,
+ loading5: false,
+ tabs2: [{ index: 0, name: '鎸夐攢閲�' }, { index: 1, name: '鎸夐攢鍞' }],
+ tabs1: [{ index: 0, name: '鎸夎鍗曢噺' }, { index: 1, name: '鎸夐攢鍞' }, { index: 2, name: '鎸変細鍛樻暟' }],
+ tabs: [{ index: 0, name: '浠婃棩' }, { index: 1, name: '杩�7鏃�' }, { index: 2, name: '杩�30鏃�' }, { index: 3, name: '杩�12鏈�' }],
+ tabName: '浠婃棩',
+ tabIndex: 0,
+ tabIndex1: 0,
+ tabIndex2: 0,
+ searchForm: {
+ topYear: null,
+ topMonth: null,
+ topYear2: null
},
- orderCorderCount: [10,10,20,10,40,10,30],
- opinionData: ['3.20', '3.21', '3.22', '3.23', '3.24', '3.25', '3.26'],
- myChart: null
+ topData: {
+ num: 0,
+ num1: 0,
+ price: 0,
+ price1: 0,
+ dateStrList: [],
+ dataList: [],
+ dataList2: [],
+ cateList: [],
+ numList: []
+ },
+ countData: {
+ totalPrice: 1000,
+ totalNum: 1000,
+ totalRefundPrice: 10000,
+ totalRefundNum: 100
+ },
+ dataList1: [],
+ dataList2: [],
+ dataList4: [],
+ dataList3: [],
+ myChart0: null,
+ myChart1: null,
+ myChart2: null,
+ myChart3: null
}
},
- mounted() {
- this.myChart = echarts.init(this.$refs.orderChange)
- window.addEventListener('resize', () => {
- this.myChart.resize()
+ created () {
+ this.config({
+ module: '宸ヤ綔鍙版暟鎹粺璁�',
+ api: '/business/workbench',
+ 'field.id': 'id',
+ 'field.main': 'id'
})
- this.renderOrderChange()
- findAllList({})
-
+ },
+ mounted () {
+ this.initTopData()
+ this.initShopRankData()
+ this.initGoodsRankData()
+ this.initIntegralData()
+ this.initCouponData()
},
methods: {
- renderOrderChange() {
- this.myChart.setOption({
+ changeYearMonth(){
+ this.initGoodsRankData()
+ this.initShopRankData()
+ },
+ changeYear(){
+ this.initIntegralData()
+ this.initCouponData()
+ },
+ initCouponData () {
+ this.loading4 = true
+ this.api.couponData({year: this.searchForm.topYear2}).then(res => {
+ res = res || {}
+ this.dataList3 = res
+ this.renderEchartOption3()
+ }).finally(() => {
+ this.loading4 = false
+ })
+ },
+ initIntegralData () {
+ this.loading5 = true
+ this.api.integralData({ year: this.searchForm.topYear2}).then(res => {
+ res = res || {}
+ this.dataList4 = res
+ this.renderEchartOption2()
+ }).finally(() => {
+ this.loading5 = false
+ })
+ },
+ initShopRankData () {
+ this.loading2 = true
+ this.api.shopRankList10({ year: this.searchForm.topYear, month: this.searchForm.topMonth ,type:this.tabIndex1}).then(res => {
+ res = res || []
+ this.dataList1 = res
+ }).finally(() => {
+ this.loading2 = false
+ })
+ },
+ initGoodsRankData () {
+ this.loading3 = true
+ this.api.goodsRankList10({ year: this.searchForm.topYear, month: this.searchForm.topMonth ,type:this.tabIndex2}).then(res => {
+ res = res || []
+ this.dataList2 = res
+ }).finally(() => {
+ this.loading3 = false
+ })
+ },
+ initTopData () {
+ this.loading1 = true
+ this.initTopEcharts()
+ this.api.businessData({ dateType: this.tabIndex }).then(res => {
+ res = res || {}
+ res.num = res.num || 0
+ res.num1 = res.num1 || 0
+ res.price = res.price || 0
+ res.price1 = res.price1 || 0
+ res.dateStrList = res.dateStrList || []
+ res.datalist2 = res.datalist2 || []
+ res.dataList = res.dataList || []
+ res.cateList = res.cateList || []
+ this.topData = res
+ this.renderEchartOption0()
+ this.renderEchartOption1()
+ }).finally(() => {
+ this.loading1 = false
+ })
+ },
+ initTopEcharts () {
+ this.myChart0 = echarts.init(this.$refs.orderCount)
+ window.addEventListener('resize', () => {
+ this.myChart0.resize()
+ })
+ this.myChart1 = echarts.init(this.$refs.cateCount)
+ window.addEventListener('resize', () => {
+ this.myChart1.resize()
+ })
+ this.myChart2 = echarts.init(this.$refs.integralCount)
+ window.addEventListener('resize', () => {
+ this.myChart2.resize()
+ })
+ this.myChart3 = echarts.init(this.$refs.couponCount)
+ window.addEventListener('resize', () => {
+ this.myChart3.resize()
+ })
+ this.renderEchartOption0()
+ this.renderEchartOption1()
+ this.renderEchartOption2()
+ this.renderEchartOption3()
+ },
+ changeTab (item) {
+ if (this.loading1) {
+ return
+ }
+ if (item.index !== this.tabIndex) {
+ this.tabName = item.name
+ this.tabIndex = item.index
+ this.initTopData()
+ }
+ },
+ changeTab1 (item) {
+ if (this.loading2) {
+ return
+ }
+ if (item.index !== this.tabIndex1) {
+ this.tabName = item.name
+ this.tabIndex1 = item.index
+ this.initShopRankData()
+ }
+ },
+ changeTab2 (item) {
+ if (this.loading3) {
+ return
+ }
+ if (item.index !== this.tabIndex2) {
+ this.tabName = item.name
+ this.tabIndex2 = item.index
+ this.initGoodsRankData()
+ }
+ },
+ renderEchartOption0 () {
+ this.myChart0.setOption({
tooltip: {
- trigger: 'axis'
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross'
+ }
},
grid: {
left: '3%',
@@ -97,55 +342,209 @@
},
toolbox: {
feature: {
-
}
+ },
+ legend: {
+ data: ['璁㈠崟閲�', '閿�鍞(鍏�)']
},
xAxis: {
type: 'category',
boundaryGap: false,
- data: this.opinionData
+ data: this.topData.dateStrList || []
},
- yAxis: {
- type: 'value'
- },
- series: [{
- name: '璁㈠崟',
- type: 'line',
- stack: '鎬婚噺',
- data: this.orderCorderCount
- }]
+ yAxis: [
+ {
+ type: 'value',
+ name: '璁㈠崟閲�',
+ min: 0
+ },
+ {
+ type: 'value',
+ name: '閿�鍞(鍏�)',
+ min: 0
+ }
+ ],
+ series: [
+ {
+ name: '璁㈠崟閲�',
+ data: this.topData.dataList || [],
+ type: 'bar'
+ },
+ {
+ name: '閿�鍞(鍏�)',
+ yAxisIndex: 1,
+ data: this.topData.dataList2 || [],
+ type: 'line'
+ }
+ ]
})
-
},
- changeCount(page) {
- if (page == 7) {
- this.orderCorderCount = [10,10,20,10,40,10,30]
- this.opinionData = ['3.20', '3.21', '3.22', '3.23', '3.24', '3.25', '3.26']
- } else {
- this.orderCorderCount = [11,10,20,10,40,10,30,20,10,20,10,40,10,30,10,10,20,10,40,10,30,10,10,20,10,40,10,30,20,40]
- this.opinionData = ['3.01','3.02','3.03','3.04','3.05','3.06','3.07','3.08','3.09','3.10','3.11','3.12','3.13','3.14','3.15','3.16','3.17','3.18','3.19','3.20', '3.21', '3.22', '3.23', '3.24', '3.25', '3.26', '3.27','3.28','3.28','3.30',]
- }
- // this.orderCorderCount.push(1)
- // this.opinionData.push(1)
- this.renderOrderChange()
-
- }
- },
+ renderEchartOption1 () {
+ const series = []
+ this.topData.cateList.forEach((item, index) => {
+ series.push( {
+ name: item.name,
+ type: 'bar',
+ stack: 'total',
+ barWidth: '60%',
+ label: {
+ // show: true
+ },
+ data: item.data || []
+ })
+ })
+ this.myChart1.setOption({
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross'
+ }
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ toolbox: {
+ feature: {
+ }
+ },
+ legend: {
+ data: this.topData.cateList || []
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ data: this.topData.dateStrList || []
+ },
+ yAxis: { type: 'value' },
+ series
+ })
+ },
+ renderEchartOption2() {
+ this.myChart2.setOption({
+ tooltip: {
+ trigger: 'item'
+ },
+ series: [
+ {
+ name: 'Access From',
+ type: 'pie',
+ radius: '50%',
+ data: [
+ { value: this.dataList4.num || 0, name: '鎵嬪姩澧炲姞' },
+ { value: this.dataList4.num1 || 0, name: '閭�璇峰ソ鍙�' },
+ { value: this.dataList4.num2 || 0, name: '娑堣垂杩斿埄' },
+ { value: this.dataList4.num3 || 0, name: '娉ㄥ唽璧犻��' }
+ ],
+ emphasis: {
+ itemStyle: {
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
+ }
+ }
+ }
+ ]
+ })
+ },
+ renderEchartOption3() {
+ this.myChart3.setOption({
+ tooltip: {
+ trigger: 'item'
+ },
+ series: [
+ {
+ name: '浼樻儬鍒稿彂鏀�',
+ type: 'pie',
+ radius: '50%',
+ data: [
+ { value: this.dataList3.num1 || 0, name: '鎶樻墸鍒�' },
+ { value: this.dataList3.num || 0, name: '婊″噺鍒�' }
+ ],
+ emphasis: {
+ itemStyle: {
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
+ }
+ }
+ }
+ ]
+ })
+ },
+ }
}
</script>
<style lang="scss" scoped>
+::v-deep .el-input--small .el-input__inner{
+ height: 22px;
+ line-height: 22px;
+ border-radius: 0;
+}
+::v-deep .el-input--small .el-input__icon{
+ height: 22px;
+ line-height: 22px;
+}
+.top-tab{
+ margin-bottom: 30px;
+ display: block;
+}
+.tab-title{
+ font-weight: 600;
+ font-size: 16px;
+ color: #222222;
+ line-height: 22px;
+ display: inline;
+}
+.tab-item{
+ display: inline;
+ margin-left: 50px;
+ .active-tab{
+ border: 1px solid #216EEE !important;
+ color: #216EEE !important;
+ }
+ .tab-btn{
+ font-weight: normal;
+ cursor: pointer;
+ border-radius: 0px;
+ margin: 0px 5px;
+ font-size: 12px;
+ border: 1px solid #999;
+ color: #999;
+ padding: 1px 5px;
+ background-color: #f2f2f2;
+ }
+}
.data {
padding-bottom: 10px;
}
.item-title {
- font-weight: 500;
-
+ font-weight: 600;
+ font-size: 14px;
+ color: #222222;
+ margin-left: 20px;
+ line-height: 22px;
}
.data-summary {
display: flex;
justify-content: space-between;
margin-top: 10px;
+ margin-bottom: 20px;
+ .green{
+ border-left: 8px solid #12bb8b;
+ }
+ .yellow{
+ border-left: 8px solid #f6cf46;
+ }
+ .blue{
+ border-left: 8px solid #216EEE;
+ }
+ .orange{
+ border-left: 8px solid #ff9e56;
+ }
.data-item {
flex: 1;
height: 80px;
@@ -153,12 +552,15 @@
box-sizing: border-box;
padding: 15px;
display: flex;
+ font-size: 14px;
flex-direction: column;
justify-content: space-between;
+ background-color: #f4f7fc;
+ color: #666;
.data-num {
font-size: 20px;
- font-weight: 700;
- color:aqua
+ font-weight: 800;
+ color: #333;
}
}
.parting {
@@ -169,9 +571,42 @@
display: flex;
justify-content: space-between;
line-height: 31px;
-}
-.bottom {
- height: 500px;
-}
-</style>
+ margin-bottom: 50px;
+ .count-left{
+ display: inline-block;
+ margin-right: 10px;
+ flex: 1;
+ .bottom {
+ height: 500px;
+ width: 100%;
+ }
+ .bottom2 {
+ height: 300px;
+ width: 100%;
+ }
+ .bottom1 {
+ height: auto;
+ width: 100%;
+ }
+ }
+ .count-right{
+ display: inline-block;
+ margin-left: 10px;
+ flex: 1;
+ .bottom {
+ height: 500px;
+ width: 100%;
+ }
+ .bottom2 {
+ height: 300px;
+ width: 100%;
+ }
+ .bottom1 {
+ height: auto;
+ width: 100%;
+ }
+ }
+}
+
+</style>
--
Gitblit v1.9.3