update
This commit is contained in:
parent
3bf7e0a813
commit
188282c4f0
@ -44,21 +44,8 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="chart-content">
|
<view class="chart-content">
|
||||||
<view class="pie-chart-container">
|
<view class="pie-chart-container">
|
||||||
<QiunDataCharts
|
<QiunDataCharts type="pie" :opts="pieChartOpts" :chartData="pieChartData" :canvas2d="true"
|
||||||
type="pie"
|
:inScrollView="true" canvasId="inventoryStructurePieChart" />
|
||||||
:opts="pieChartOpts"
|
|
||||||
:chartData="pieChartData"
|
|
||||||
:canvas2d="true"
|
|
||||||
:inScrollView="true"
|
|
||||||
canvasId="inventoryStructurePieChart"
|
|
||||||
/>
|
|
||||||
<view class="pie-legend">
|
|
||||||
<view class="legend-item" v-for="(item, index) in categoryData" :key="index">
|
|
||||||
<view class="legend-color" :style="{ backgroundColor: item.color }"></view>
|
|
||||||
<text class="legend-name">{{ item.name }}</text>
|
|
||||||
<text class="legend-value">{{ item.percentage }}%</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -71,14 +58,8 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="chart-content">
|
<view class="chart-content">
|
||||||
<view class="bar-chart-container">
|
<view class="bar-chart-container">
|
||||||
<QiunDataCharts
|
<QiunDataCharts type="column" :opts="barChartOpts" :chartData="barChartData" :canvas2d="true"
|
||||||
type="column"
|
:inScrollView="true" canvasId="inventoryStructureBarChart" />
|
||||||
:opts="barChartOpts"
|
|
||||||
:chartData="barChartData"
|
|
||||||
:canvas2d="true"
|
|
||||||
:inScrollView="true"
|
|
||||||
canvasId="inventoryStructureBarChart"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="chart-legend">
|
<view class="chart-legend">
|
||||||
<view class="legend-item">
|
<view class="legend-item">
|
||||||
@ -87,7 +68,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="legend-item">
|
<view class="legend-item">
|
||||||
<view class="legend-dot value"></view>
|
<view class="legend-dot value"></view>
|
||||||
<text class="legend-text">库存价值(÷1000)</text>
|
<text class="legend-text">库存价值</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -97,34 +78,30 @@
|
|||||||
<view class="chart-card">
|
<view class="chart-card">
|
||||||
<view class="chart-header">
|
<view class="chart-header">
|
||||||
<text class="chart-title">库存详细数据</text>
|
<text class="chart-title">库存详细数据</text>
|
||||||
<view class="table-actions">
|
|
||||||
<text class="action-btn" @click="toggleFilter">筛选</text>
|
|
||||||
<text class="action-btn" @click="exportData">导出</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="category-cards">
|
<view class="category-cards">
|
||||||
<view class="category-card" v-for="(item, index) in categoryData" :key="index">
|
<view class="category-card" v-for="(item, index) in categoryData" :key="index">
|
||||||
<view class="category-header">
|
<view class="category-header">
|
||||||
<view class="category-type-tag" :style="{ backgroundColor: item.color }">
|
<view class="category-type-tag">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</view>
|
</view>
|
||||||
<text class="category-percentage">{{ item.percentage }}%</text>
|
<text class="category-percentage">{{ item.value }}%</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="category-body">
|
<view class="category-body">
|
||||||
<view class="category-metrics">
|
<view class="category-metrics">
|
||||||
<view class="metric-item">
|
<view class="metric-item">
|
||||||
<text class="metric-label">库存数量</text>
|
<text class="metric-label">库存数量</text>
|
||||||
<text class="metric-value">{{ formatNumber(item.quantity) }}件</text>
|
<text class="metric-value">件</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="metric-divider"></view>
|
<view class="metric-divider"></view>
|
||||||
<view class="metric-item">
|
<view class="metric-item">
|
||||||
<text class="metric-label">库存价值</text>
|
<text class="metric-label">库存价值</text>
|
||||||
<text class="metric-value">¥{{ formatMoney(item.value) }}万</text>
|
<text class="metric-value">¥万</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="metric-divider"></view>
|
<view class="metric-divider"></view>
|
||||||
<view class="metric-item">
|
<view class="metric-item">
|
||||||
<text class="metric-label">平均单价</text>
|
<text class="metric-label">平均单价</text>
|
||||||
<text class="metric-value">¥{{ formatMoney(item.avgPrice) }}</text>
|
<text class="metric-value">¥</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="category-trend">
|
<view class="category-trend">
|
||||||
@ -142,6 +119,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
||||||
|
import request from "@/util/index.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -154,82 +132,8 @@ export default {
|
|||||||
totalCategories: 8,
|
totalCategories: 8,
|
||||||
totalQuantity: 485672,
|
totalQuantity: 485672,
|
||||||
totalValue: 3847.56,
|
totalValue: 3847.56,
|
||||||
|
|
||||||
// 商品类别数据
|
// 商品类别数据
|
||||||
categoryData: [
|
categoryData: []
|
||||||
{
|
|
||||||
name: '保健品',
|
|
||||||
quantity: 156234,
|
|
||||||
value: 1256.78,
|
|
||||||
percentage: 32.2,
|
|
||||||
color: '#576EFF',
|
|
||||||
avgPrice: 80.45,
|
|
||||||
trend: 5.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '茶叶',
|
|
||||||
quantity: 128456,
|
|
||||||
value: 987.34,
|
|
||||||
percentage: 26.5,
|
|
||||||
color: '#52C41A',
|
|
||||||
avgPrice: 76.84,
|
|
||||||
trend: -2.1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '食品',
|
|
||||||
quantity: 98567,
|
|
||||||
value: 654.23,
|
|
||||||
percentage: 20.3,
|
|
||||||
color: '#FAAD14',
|
|
||||||
avgPrice: 66.38,
|
|
||||||
trend: 8.7
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '饮品',
|
|
||||||
quantity: 56789,
|
|
||||||
value: 456.78,
|
|
||||||
percentage: 11.7,
|
|
||||||
color: '#FF7875',
|
|
||||||
avgPrice: 80.46,
|
|
||||||
trend: 3.4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '工艺品',
|
|
||||||
quantity: 23456,
|
|
||||||
value: 345.67,
|
|
||||||
percentage: 4.8,
|
|
||||||
color: '#B37FEB',
|
|
||||||
avgPrice: 147.43,
|
|
||||||
trend: -1.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '纺织品',
|
|
||||||
quantity: 12345,
|
|
||||||
value: 98.76,
|
|
||||||
percentage: 2.5,
|
|
||||||
color: '#13C2C2',
|
|
||||||
avgPrice: 80.00,
|
|
||||||
trend: 12.3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '化妆品',
|
|
||||||
quantity: 8765,
|
|
||||||
value: 34.56,
|
|
||||||
percentage: 1.8,
|
|
||||||
color: '#FF85C0',
|
|
||||||
avgPrice: 39.45,
|
|
||||||
trend: 6.8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '其他',
|
|
||||||
quantity: 560,
|
|
||||||
value: 13.44,
|
|
||||||
percentage: 0.2,
|
|
||||||
color: '#8C8C8C',
|
|
||||||
avgPrice: 240.00,
|
|
||||||
trend: -8.9
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -240,7 +144,7 @@ export default {
|
|||||||
series: [{
|
series: [{
|
||||||
data: this.categoryData.map(item => ({
|
data: this.categoryData.map(item => ({
|
||||||
name: item.name,
|
name: item.name,
|
||||||
value: item.quantity
|
value: Number(item.value)
|
||||||
}))
|
}))
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
@ -249,11 +153,10 @@ export default {
|
|||||||
// 饼图配置
|
// 饼图配置
|
||||||
pieChartOpts() {
|
pieChartOpts() {
|
||||||
return {
|
return {
|
||||||
color: this.categoryData.map(item => item.color),
|
|
||||||
padding: [5, 5, 5, 5],
|
padding: [5, 5, 5, 5],
|
||||||
dataLabel: true,
|
dataLabel: true,
|
||||||
legend: {
|
legend: {
|
||||||
show: false
|
show: true
|
||||||
},
|
},
|
||||||
extra: {
|
extra: {
|
||||||
pie: {
|
pie: {
|
||||||
@ -325,8 +228,30 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onReady() {
|
||||||
|
// 获取整个组件的数据
|
||||||
|
this.handleGetAllData()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 获取整个组件的数据
|
||||||
|
handleGetAllData() {
|
||||||
|
// 获取商品类别数量占比
|
||||||
|
this.handleGetShopTypeNumberRate()
|
||||||
|
},
|
||||||
|
// 获取商品类别数量占比
|
||||||
|
async handleGetShopTypeNumberRate() {
|
||||||
|
let req = {
|
||||||
|
ProvinceCode: "530000",
|
||||||
|
type: "encryption"
|
||||||
|
}
|
||||||
|
const data = await request.$webPost(
|
||||||
|
"CommercialApi/BaseInfo/GetBrandStructureAnalysis",
|
||||||
|
req
|
||||||
|
);
|
||||||
|
let list = data.Result_Data.List
|
||||||
|
console.log('商品类别数量占比', list);
|
||||||
|
this.categoryData = list
|
||||||
|
},
|
||||||
formatNumber(num) {
|
formatNumber(num) {
|
||||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
|
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
|
||||||
},
|
},
|
||||||
@ -425,17 +350,41 @@ export default {
|
|||||||
|
|
||||||
&.categories {
|
&.categories {
|
||||||
background: linear-gradient(135deg, #1890ff, #40a9ff);
|
background: linear-gradient(135deg, #1890ff, #40a9ff);
|
||||||
&::after { content: '📊'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
|
||||||
|
&::after {
|
||||||
|
content: '📊';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.quantity {
|
&.quantity {
|
||||||
background: linear-gradient(135deg, #52c41a, #73d13d);
|
background: linear-gradient(135deg, #52c41a, #73d13d);
|
||||||
&::after { content: '📦'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
|
||||||
|
&::after {
|
||||||
|
content: '📦';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.value {
|
&.value {
|
||||||
background: linear-gradient(135deg, #faad14, #ffc53d);
|
background: linear-gradient(135deg, #faad14, #ffc53d);
|
||||||
&::after { content: '💰'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
|
||||||
|
&::after {
|
||||||
|
content: '💰';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,25 +48,16 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="chart-content">
|
<view class="chart-content">
|
||||||
<view class="growth-chart-container">
|
<view class="growth-chart-container">
|
||||||
<QiunDataCharts
|
<QiunDataCharts type="line" :opts="growthChartOpts" :chartData="growthChartData" :canvas2d="true"
|
||||||
type="line"
|
:inScrollView="true" canvasId="memberGrowthChart" />
|
||||||
:opts="growthChartOpts"
|
|
||||||
:chartData="growthChartData"
|
|
||||||
:canvas2d="true"
|
|
||||||
:inScrollView="true"
|
|
||||||
canvasId="memberGrowthChart"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="chart-controls">
|
<view class="chart-controls">
|
||||||
<text class="control-btn"
|
<text class="control-btn" :class="{ active: growthPeriod === 'month' }"
|
||||||
:class="{ active: growthPeriod === 'month' }"
|
@click="changeGrowthPeriod('month')">月度</text>
|
||||||
@click="changeGrowthPeriod('month')">月度</text>
|
<text class="control-btn" :class="{ active: growthPeriod === 'quarter' }"
|
||||||
<text class="control-btn"
|
@click="changeGrowthPeriod('quarter')">季度</text>
|
||||||
:class="{ active: growthPeriod === 'quarter' }"
|
<text class="control-btn" :class="{ active: growthPeriod === 'year' }"
|
||||||
@click="changeGrowthPeriod('quarter')">季度</text>
|
@click="changeGrowthPeriod('year')">年度</text>
|
||||||
<text class="control-btn"
|
|
||||||
:class="{ active: growthPeriod === 'year' }"
|
|
||||||
@click="changeGrowthPeriod('year')">年度</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -78,14 +69,16 @@
|
|||||||
<text class="chart-subtitle">不同等级会员数量占比</text>
|
<text class="chart-subtitle">不同等级会员数量占比</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="member-levels">
|
<view class="member-levels">
|
||||||
<view class="level-item" v-for="(level, index) in memberLevels" :key="index">
|
<view class="level-item" v-for="(item, index) in memberLevels" :key="index">
|
||||||
<view class="level-info">
|
<view class="level-info">
|
||||||
<view class="level-badge" :class="level.type">{{ level.name }}</view>
|
<view class="level-badge">{{ memberLevelObj && item.label &&
|
||||||
<text class="level-count">{{ formatNumber(level.count) }}</text>
|
memberLevelObj[Number(item.label)]
|
||||||
|
? memberLevelObj[Number(item.label)] : '' }}</view>
|
||||||
|
<text class="level-count">{{ formatNumber(item.value) }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="level-progress">
|
<view class="level-progress">
|
||||||
<view class="progress-bar" :style="{ width: level.percentage + '%' }"></view>
|
<view class="progress-bar" :style="{ width: item.key + '%' }"></view>
|
||||||
<text class="progress-text">{{ level.percentage }}%</text>
|
<text class="progress-text">{{ item.key }}%</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -99,13 +92,12 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="activity-analysis">
|
<view class="activity-analysis">
|
||||||
<view class="activity-grid">
|
<view class="activity-grid">
|
||||||
<view class="activity-item" v-for="(activity, index) in activityData" :key="index">
|
<view class="activity-item" v-for="(item, index) in activityData" :key="index">
|
||||||
<view class="activity-icon" :class="activity.status">
|
<text class="activity-label">{{ memberLevelObj && item.label &&
|
||||||
<text class="icon-text">{{ activity.icon }}</text>
|
memberLevelObj[Number(item.label)]
|
||||||
</view>
|
? memberLevelObj[Number(item.label)] : '' }}</text>
|
||||||
<text class="activity-label">{{ activity.label }}</text>
|
<text class="activity-count">{{ formatNumber(item.value) }}</text>
|
||||||
<text class="activity-count">{{ formatNumber(activity.count) }}</text>
|
<text class="activity-percent">{{ item.key }}%</text>
|
||||||
<text class="activity-percent">{{ activity.percent }}%</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -118,16 +110,16 @@
|
|||||||
<text class="chart-subtitle">不同渠道会员获取情况</text>
|
<text class="chart-subtitle">不同渠道会员获取情况</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="source-chart">
|
<view class="source-chart">
|
||||||
<view class="source-item" v-for="(source, index) in memberSources" :key="index">
|
<view class="source-item" v-for="(item, index) in memberSources" :key="index">
|
||||||
<view class="source-info">
|
<view class="source-info">
|
||||||
<text class="source-name">{{ source.name }}</text>
|
<text class="source-name">{{ item.label }}</text>
|
||||||
<text class="source-count">{{ formatNumber(source.count) }}</text>
|
<text class="source-count">{{ formatNumber(item.value) }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="source-progress">
|
<view class="source-progress">
|
||||||
<view class="source-bar">
|
<view class="source-bar">
|
||||||
<view class="bar-fill" :style="{ width: source.percentage + '%' }"></view>
|
<view class="bar-fill" :style="{ width: item.key + '%' }"></view>
|
||||||
</view>
|
</view>
|
||||||
<text class="source-percent">{{ source.percentage }}%</text>
|
<text class="source-percent">{{ item.key }}%</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -206,6 +198,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
||||||
|
import request from "@/util/index.js";
|
||||||
|
import { wrapTreeNode } from "../../../util/dateTime";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -246,25 +240,10 @@ export default {
|
|||||||
currentTime: '14:32',
|
currentTime: '14:32',
|
||||||
lastActiveTime: '14:28',
|
lastActiveTime: '14:28',
|
||||||
lastPurchaseTime: '14:15',
|
lastPurchaseTime: '14:15',
|
||||||
memberLevels: [
|
memberLevels: [], // 会员等级
|
||||||
{ name: '普通会员', type: 'normal', count: 89456, percentage: 57.1 },
|
memberLevelObj: {},//会员类型的枚举
|
||||||
{ name: '银卡会员', type: 'silver', count: 45678, percentage: 29.1 },
|
activityData: [], // 会员活跃度
|
||||||
{ name: '金卡会员', type: 'gold', count: 18900, percentage: 12.1 },
|
memberSources: [],// 会员来源
|
||||||
{ name: '钻石会员', type: 'diamond', count: 2755, percentage: 1.7 }
|
|
||||||
],
|
|
||||||
activityData: [
|
|
||||||
{ label: '高度活跃', icon: '🔥', count: 23456, percent: 26.2, status: 'high' },
|
|
||||||
{ label: '中度活跃', icon: '⚡', count: 45678, percent: 51.1, status: 'medium' },
|
|
||||||
{ label: '低度活跃', icon: '👤', count: 15678, percent: 17.5, status: 'low' },
|
|
||||||
{ label: '沉默会员', icon: '😴', count: 4677, percent: 5.2, status: 'inactive' }
|
|
||||||
],
|
|
||||||
memberSources: [
|
|
||||||
{ name: '小程序注册', count: 67890, percentage: 43.3 },
|
|
||||||
{ name: '线下扫码', count: 45678, percentage: 29.1 },
|
|
||||||
{ name: '分享邀请', count: 23456, percentage: 15.0 },
|
|
||||||
{ name: '活动推广', count: 18965, percentage: 12.1 },
|
|
||||||
{ name: '其他渠道', count: 800, percentage: 0.5 }
|
|
||||||
],
|
|
||||||
retentionData: [
|
retentionData: [
|
||||||
{ period: '次日留存', rate: 85.6 },
|
{ period: '次日留存', rate: 85.6 },
|
||||||
{ period: '7日留存', rate: 78.9 },
|
{ period: '7日留存', rate: 78.9 },
|
||||||
@ -325,8 +304,126 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onReady() {
|
||||||
|
// 获取整个组件的数据
|
||||||
|
this.handleGetAllData()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 获取整个组件的数据
|
||||||
|
handleGetAllData() {
|
||||||
|
// 获取会员等级分布的数据
|
||||||
|
this.handleGetMemberLevelData()
|
||||||
|
// 获取会员活跃度分析
|
||||||
|
this.handleGetMemberActiveData()
|
||||||
|
// 获取会员来源分析
|
||||||
|
this.handleGetMemberComeData()
|
||||||
|
},
|
||||||
|
sortData(data) {
|
||||||
|
return data.sort((a, b) => b.value - a.value); // 按照 'value' 升序排序
|
||||||
|
},
|
||||||
|
// 获取会员来源分析
|
||||||
|
async handleGetMemberComeData() {
|
||||||
|
const req = {
|
||||||
|
CalcType: "5",
|
||||||
|
OwnerUnitId: 911,
|
||||||
|
ExcludeTest: true,
|
||||||
|
StartDate: '',
|
||||||
|
EndDate: "",
|
||||||
|
MembershipType: "",
|
||||||
|
MembershipLevel: "",
|
||||||
|
MembershipTarget: "",
|
||||||
|
type: "encryption"
|
||||||
|
}
|
||||||
|
const data = await request.$posPost(
|
||||||
|
"MemberApi/Member/GetMembershipCount",
|
||||||
|
req
|
||||||
|
);
|
||||||
|
let list = data.Result_Data.List
|
||||||
|
this.memberSources = this.sortData(list)
|
||||||
|
},
|
||||||
|
// 获取会员活跃度分析
|
||||||
|
async handleGetMemberActiveData() {
|
||||||
|
const req = {
|
||||||
|
CalcType: "4",
|
||||||
|
OwnerUnitId: 911,
|
||||||
|
ExcludeTest: true,
|
||||||
|
StartDate: '',
|
||||||
|
EndDate: "",
|
||||||
|
MembershipType: "",
|
||||||
|
MembershipLevel: "",
|
||||||
|
MembershipTarget: "",
|
||||||
|
type: "encryption"
|
||||||
|
}
|
||||||
|
const data = await request.$posPost(
|
||||||
|
"MemberApi/Member/GetMembershipCount",
|
||||||
|
req
|
||||||
|
);
|
||||||
|
let list = data.Result_Data.List
|
||||||
|
console.log('会员活跃度分析', list);
|
||||||
|
let res = []
|
||||||
|
if (list && list.length > 0) {
|
||||||
|
list.forEach((item) => {
|
||||||
|
if (item.value > 0) {
|
||||||
|
res.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.activityData = this.sortData(res)
|
||||||
|
},
|
||||||
|
// 获取会员等级分布的数据
|
||||||
|
async handleGetMemberLevelData() {
|
||||||
|
// 请求一下会员等级的枚举
|
||||||
|
let objReq = {
|
||||||
|
FIELDEXPLAIN_FIELD: "MEMBERSHIP_LEVEL_YN",
|
||||||
|
FIELDEXPLAIN_ID: "",
|
||||||
|
FIELDENUM_PID: "",
|
||||||
|
FIELDENUM_STATUS: "",
|
||||||
|
SearchKey: "",
|
||||||
|
type: "encryption"
|
||||||
|
}
|
||||||
|
let levelObj = await request.$posPost(
|
||||||
|
"MemberApi/Dictionary/GetNestingFIELDENUMList",
|
||||||
|
objReq
|
||||||
|
);
|
||||||
|
let objList = wrapTreeNode(levelObj.Result_Data.List)
|
||||||
|
let levelResObj = {}
|
||||||
|
if (objList && objList.length > 0) {
|
||||||
|
objList.forEach((item) => {
|
||||||
|
levelResObj[item.FIELDENUM_VALUE] = item.FIELDENUM_NAME
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.memberLevelObj = levelResObj
|
||||||
|
console.log('this.memberLevelObjthis.memberLevelObj', this.memberLevelObj);
|
||||||
|
|
||||||
|
|
||||||
|
const req = {
|
||||||
|
CalcType: "2",
|
||||||
|
OwnerUnitId: 911,
|
||||||
|
ExcludeTest: true,
|
||||||
|
StartDate: '',
|
||||||
|
EndDate: "",
|
||||||
|
MembershipType: "",
|
||||||
|
MembershipLevel: "",
|
||||||
|
MembershipTarget: "",
|
||||||
|
type: "encryption"
|
||||||
|
}
|
||||||
|
const data = await request.$posPost(
|
||||||
|
"MemberApi/Member/GetMembershipCount",
|
||||||
|
req
|
||||||
|
);
|
||||||
|
let list = data.Result_Data.List
|
||||||
|
console.log('会员等级分布', list);
|
||||||
|
|
||||||
|
let res = []
|
||||||
|
if (list && list.length > 0) {
|
||||||
|
list.forEach((item) => {
|
||||||
|
if (item.value > 0) {
|
||||||
|
res.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.memberLevels = this.sortData(res)
|
||||||
|
},
|
||||||
formatNumber(num) {
|
formatNumber(num) {
|
||||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||||
},
|
},
|
||||||
@ -408,7 +505,9 @@ export default {
|
|||||||
background: linear-gradient(135deg, @primary-color, @secondary-color);
|
background: linear-gradient(135deg, @primary-color, @secondary-color);
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
.metric-title, .metric-unit, .metric-trend {
|
.metric-title,
|
||||||
|
.metric-unit,
|
||||||
|
.metric-trend {
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,17 +535,41 @@ export default {
|
|||||||
|
|
||||||
&.total {
|
&.total {
|
||||||
background: linear-gradient(135deg, @primary-color, @secondary-color);
|
background: linear-gradient(135deg, @primary-color, @secondary-color);
|
||||||
&::after { content: '👥'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
|
||||||
|
&::after {
|
||||||
|
content: '👥';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: linear-gradient(135deg, @success-color, #73d13d);
|
background: linear-gradient(135deg, @success-color, #73d13d);
|
||||||
&::after { content: '✨'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
|
||||||
|
&::after {
|
||||||
|
content: '✨';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.new {
|
&.new {
|
||||||
background: linear-gradient(135deg, @warning-color, #ffc53d);
|
background: linear-gradient(135deg, @warning-color, #ffc53d);
|
||||||
&::after { content: '🆕'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
|
||||||
|
&::after {
|
||||||
|
content: '🆕';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,7 +648,7 @@ export default {
|
|||||||
animation: pulse 2s infinite;
|
animation: pulse 2s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.growth-chart-container {
|
.growth-chart-container {
|
||||||
margin-bottom: 24rpx;
|
margin-bottom: 24rpx;
|
||||||
@ -566,27 +689,11 @@ export default {
|
|||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
font-size: 22rpx;
|
font-size: 22rpx;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: white;
|
color: #010c13;
|
||||||
|
background: linear-gradient(135deg, #b9f2ff, #69c0ff);
|
||||||
&.normal {
|
|
||||||
background: @text-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.silver {
|
|
||||||
background: @silver;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.gold {
|
|
||||||
background: @gold;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.diamond {
|
|
||||||
background: linear-gradient(135deg, #b9f2ff, #69c0ff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.level-count {
|
.level-count {
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -666,7 +773,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.activity-count {
|
.activity-count {
|
||||||
font-size: 28rpx;
|
font-size: 24rpx;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: @text-primary;
|
color: @text-primary;
|
||||||
margin-bottom: 4rpx;
|
margin-bottom: 4rpx;
|
||||||
@ -674,7 +781,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.activity-percent {
|
.activity-percent {
|
||||||
font-size: 20rpx;
|
font-size: 24rpx;
|
||||||
color: @text-secondary;
|
color: @text-secondary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -853,9 +960,11 @@ export default {
|
|||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -260,11 +260,7 @@ export default {
|
|||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
disableGrid: true,
|
disableGrid: true,
|
||||||
type: 'category',
|
type: 'category'
|
||||||
data: Array.from({ length: 30 }, (_, index) => index + 1),
|
|
||||||
format: function (val) {
|
|
||||||
return (val % 5 === 0) ? val : '';
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
gridType: 'dash',
|
gridType: 'dash',
|
||||||
@ -312,14 +308,17 @@ export default {
|
|||||||
let orderData = [] // 销量
|
let orderData = [] // 销量
|
||||||
let amountData = [] // 销售额
|
let amountData = [] // 销售额
|
||||||
if (list && list.length > 0) {
|
if (list && list.length > 0) {
|
||||||
list.forEach((item) => {
|
list.forEach((item, index) => {
|
||||||
categories.push(item.StatisticsDate.split('/')[2])
|
const day = parseInt(item.StatisticsDate.split('/')[2])
|
||||||
|
if (day % 5 === 0 || day === 1) {
|
||||||
|
categories.push(day + '日')
|
||||||
|
}
|
||||||
orderData.push(item.TicketCount)
|
orderData.push(item.TicketCount)
|
||||||
amountData.push(item.SellAmount)
|
amountData.push(item.SellAmount)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.trendData = {
|
this.trendData = {
|
||||||
categories: orderData,
|
categories: categories,
|
||||||
orderData: orderData,
|
orderData: orderData,
|
||||||
amountData: amountData
|
amountData: amountData
|
||||||
}
|
}
|
||||||
|
|||||||
@ -182,7 +182,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeTab: 0,
|
activeTab: 1,
|
||||||
tabList: [
|
tabList: [
|
||||||
{ name: '经营数据分析', key: 'business' },
|
{ name: '经营数据分析', key: 'business' },
|
||||||
{ name: '供应链数据分析', key: 'supply' },
|
{ name: '供应链数据分析', key: 'supply' },
|
||||||
|
|||||||
@ -6,6 +6,7 @@ export default {
|
|||||||
|
|
||||||
mpUrl: 'https://eshangtech.com:18998/Coop.Merchant/Handler/handler_ajax.ashx', // 接口
|
mpUrl: 'https://eshangtech.com:18998/Coop.Merchant/Handler/handler_ajax.ashx', // 接口
|
||||||
apiurl: 'https://eshangtech.com:18900/', // web api正式接口地址
|
apiurl: 'https://eshangtech.com:18900/', // web api正式接口地址
|
||||||
|
posApiurl: 'https://pos.eshangtech.com/', // web api正式接口地址
|
||||||
// EshangUrl: 'https://eshangtech.com/',
|
// EshangUrl: 'https://eshangtech.com/',
|
||||||
// apiurl: 'https://erysfeipeng.oicp.net/', // web api
|
// apiurl: 'https://erysfeipeng.oicp.net/', // web api
|
||||||
testApiurl: 'http://dev.eshangtech.com:8001/', // web api测试接口地址
|
testApiurl: 'http://dev.eshangtech.com:8001/', // web api测试接口地址
|
||||||
|
|||||||
@ -31,6 +31,9 @@ export default {
|
|||||||
data.action_type = controller
|
data.action_type = controller
|
||||||
return this.post(data)
|
return this.post(data)
|
||||||
},
|
},
|
||||||
|
$posPost: function (controller, data) {
|
||||||
|
return Api.request('POST', ApiPath.posApiurl + controller, data || {}, true)
|
||||||
|
},
|
||||||
$webGet: function (controller, data) { // webapi
|
$webGet: function (controller, data) { // webapi
|
||||||
return Api.request('GET', ApiPath.apiurl + controller, data || {}, true)
|
return Api.request('GET', ApiPath.apiurl + controller, data || {}, true)
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user