ccy_DIB/pages/everdayRenven/AnhuiIndex.vue
ylj20011123 870d96fb3c update
2025-11-14 18:47:09 +08:00

2557 lines
54 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<view class="page-body" v-if="showPage">
<AnhHead :today="today" :headMsg="headMsg" :lastDay="lastDay"
:groupType="theRequest && theRequest.GroupType" :provinceCode="theRequest && theRequest.ProvinceCode"
@bindDateChange="bindDateChange" :isup="isup" :nowDay="nowDay"
:selectDate="theRequest && theRequest.time" @toggle="toggleCard" :currentMoney="currentMoney"></AnhHead>
<!--营收占比的上面组件 -->
<view class="main-content">
<!--安徽省 昨日营收占比 -->
<view v-if="theRequest && theRequest.GroupType != 1010">
<view class="section-header">
<view class="section-title">
<view class="section-icon">
<text class="icon-emoji">📊</text>
</view>
<text class="section-text">营收占比</text>
</view>
</view>
<view class="analysis-container">
<view class="modern-tabs">
<view class="tab-item" @click="selectTab('nowTab', 1)"
v-if="theRequest.ProvinceCode == 340000" :class="{ 'active': nowTab == 1 }">
<view class="tab-icon">🏢</view>
<view class="tab-label">经营模式</view>
</view>
<view class="tab-item" @click="selectTab('nowTab', 2)" :class="{ 'active': nowTab == 2 }">
<view class="tab-icon">🏪</view>
<view class="tab-label">经营业态</view>
</view>
<view class="tab-item" @click="selectTab('nowTab', 3)"
v-if="areaProgress.length && areaProgress.length > 1"
:class="{ 'active': nowTab == 3 }">
<view class="tab-icon">🗺</view>
<view class="tab-label">区域营收</view>
</view>
<view class="tab-item" @click="selectTab('nowTab', 4)"
v-if="theRequest.ProvinceCode == 340000 && theRequest.GroupType == 1000"
:class="{ 'active': nowTab == 4 }">
<view class="tab-icon">🚗</view>
<view class="tab-label">车流分析</view>
</view>
</view>
<view class="content-wrapper">
<view class="chart-section" v-show="nowTab == 1"
v-if="modelProgress.length > 0 && theRequest.ProvinceCode == 340000">
<view class="chart-container">
<canvas canvas-id="modelCont" id="modelCont" class="modern-chart"
@touchstart="touchPie($event, 'modelCont')"></canvas>
</view>
<view class="data-cards">
<view class="data-card" v-for="(item, o) in modelProgress" :key="o">
<view class="card-header">
<view class="category-name">{{ item.name }}</view>
<view class="percentage">{{ item.bili }}%</view>
</view>
<view class="amount">¥{{ item.data }}</view>
<view class="progress-bar">
<view class="progress-fill" :style="{ 'width': item.bili + '%' }"></view>
</view>
</view>
</view>
</view>
<view class="chart-section" v-show="nowTab == 2" v-if="regionProgress.length > 0">
<view class="chart-container">
<canvas canvas-id="businessCont" id="businessCont" class="modern-chart"
@touchstart="touchPie($event, 'businessCont')"></canvas>
</view>
<view class="data-cards">
<view class="data-card" v-for="(item, o) in regionProgress" :key="o">
<view class="card-header">
<view class="category-name">{{ item.name }}</view>
<view class="percentage">{{ item.bili }}%</view>
</view>
<view class="amount">¥{{ item.data }}</view>
<view class="progress-bar">
<view class="progress-fill" :style="{ 'width': item.bili + '%' }"></view>
</view>
</view>
</view>
</view>
<view class="chart-section" v-show="nowTab == 3" v-if="areaProgress.length > 0">
<view class="chart-container">
<canvas canvas-id="areaCont" id="areaCont" class="modern-chart"
@touchstart="touchPie($event, 'areaCont')"></canvas>
</view>
<view class="data-cards">
<view class="data-card" v-for="(item, o) in areaProgress" :key="o">
<view class="card-header">
<view class="category-name">{{ item.name }}</view>
<view class="percentage">{{ item.bili }}%</view>
</view>
<view class="amount">¥{{ item.data }}</view>
<view class="progress-bar">
<view class="progress-fill" :style="{ 'width': item.bili + '%' }"></view>
</view>
</view>
</view>
</view>
<view class="traffic-analysis" v-show="nowTab == 4"
v-if="bayonetProgress && bayonetProgress.length > 0">
<view class="traffic-regions">
<view class="region-section" v-for="(item, o) in bayonetProgress" :key="o">
<view class="region-title">
<view class="region-icon">🗺️</view>
<view class="region-name">{{ item.name }}</view>
</view>
<view class="service-areas">
<view class="service-area-card" v-for="(child, o) in item.list" :key="o">
<view class="area-header">
<view class="area-name">🏢 {{ child.name }}</view>
<view class="flow-ratio">{{ child.bili }}%</view>
</view>
<view class="flow-stats">
<view class="stat-item">
<view class="stat-label">入区流量</view>
<view class="stat-value">{{ child.data }}</view>
</view>
<view class="stat-divider"></view>
<view class="stat-item">
<view class="stat-label">断面流量</view>
<view class="stat-value">{{ child.flow }}</view>
</view>
</view>
<view class="vehicle-breakdown">
<view class="vehicle-item" v-for="(childItem, idx) in child.list"
:key="idx">
<view class="direction-header">
<view class="direction-name">{{ childItem.name }}区</view>
<view class="direction-ratio">{{ childItem.bili }}%</view>
</view>
<view class="vehicle-types">
<text class="vehicle-type">🚛 {{
childItem.LargeVehicle_Count }}</text>
<text class="vehicle-type">🚐 {{
childItem.MediumVehicle_Count }}</text>
<text class="vehicle-type">🚗 {{ childItem.MinVehicle_Count
}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 日结上传区域 -->
<view class="upload-section" v-if="regionList.length > 0">
<view class="upload-header">
<view class="upload-title">
<view class="upload-icon">📊</view>
<view class="upload-text">日结上传状态</view>
</view>
<view class="upload-summary">
<view class="summary-label">上传情况</view>
<view class="summary-value">{{ headMsg.uploadState }}</view>
</view>
</view>
</view>
<template v-if="theRequest && theRequest.GroupType == 1020 && regionList.length">
<view class="service-list">
<view v-for="(item, i) in regionList[0].child" :key="i" class="service-card"
@click="toDetail(item)">
<view class="service-header">
<view class="service-info">
<view class="service-name">🏢 {{ item.serverpart_Name }}</view>
<view class="service-revenue">¥{{ $util.fmoney(item.cashpay, 2) }}</view>
</view>
<view class="service-status">
<view class="upload-rate"
:class="{ 'warning': item.uploadcount != item.totalcount }">
{{ item.totalcount > item.uploadcount ?
$util.fmoney((item.uploadcount / item.totalcount) * 100, 2) : 100 }}%
</view>
<view class="upload-fraction"
:class="{ 'incomplete': item.uploadcount != item.totalcount }">
{{ item.uploadcount }}/{{ item.totalcount }}
</view>
</view>
</view>
<view class="service-indicator">
<view class="status-dot"
:class="{ 'complete': item.uploadcount == item.totalcount, 'incomplete': item.uploadcount != item.totalcount }">
</view>
<view class="arrow-icon"></view>
</view>
</view>
</view>
</template>
<template v-else-if="theRequest && theRequest.GroupType == 1000">
<view class="region-list" v-show="regionShow1">
<block v-for="(item, i) in regionList" :key="i">
<view class="region-card" @click="toggleRegion(item)">
<view class="region-main">
<view class="region-info">
<view class="region-name">{{ item.name }}</view>
<view class="region-revenue">{{ $util.fmoney(item.cashpay, 2) }}</view>
</view>
<view class="region-metrics">
<view class="metric-item">
<view class="metric-label">上传率</view>
<view class="metric-value rate"
:class="{ 'incomplete': item.uploadcount != item.totalcount }">
{{ (item.totalcount > item.uploadcount) ?
$util.fmoney((item.uploadcount / item.totalcount) * 100, 2) : '100.00'
}}%
</view>
</view>
<view class="metric-item">
<view class="metric-label">状态</view>
<view class="metric-value fraction"
:class="{ 'incomplete': item.uploadcount != item.totalcount }">
{{ item.uploadcount }}/{{ item.totalcount }}
</view>
</view>
<view class="expand-indicator" :class="{ 'expanded': item.show }">
<view class="expand-icon"></view>
</view>
</view>
</view>
<view class="service-sublist" v-show="item.show">
<view class="subservice-card" v-for="(child, index) in item.child"
:class="{ 'visited': child.visited }" :key="index"
@click.stop="toDetail(child)">
<view class="subservice-info">
<view class="subservice-name">{{ child.serverpart_Name }}</view>
<view class="subservice-revenue">{{ $util.fmoney(child.cashpay, 2) }}
</view>
</view>
<view class="subservice-status"
:class="{ 'incomplete': child.uploadcount != child.totalcount }">
{{ child.uploadcount }}/{{ child.totalcount }}
</view>
<view class="subservice-arrow"></view>
</view>
</view>
</view>
</block>
</view>
</template>
<template v-else>
<shopCell v-for="(item, i) in regionList" :key="i" :item='item' @toggleShow="toggleShow" :i='i' />
</template>
</view>
<template v-if="theRequest && theRequest.ProvinceCode == '620000' || theRequest.ProvinceCode == '530000'">
<view class="uni-inline-item modle-title">
<image src="/static/images/revenue/product-ranking.png" mode="aspectFit"></image>
<text class="strong-text">商品销售排行</text>
</view>
<RankContent :wechatPushSalesList="wechatPushSalesList" v-if="!isLoading"></RankContent>
</template>
</view>
<view v-if="!showPage && !isLoading">
<noFound :nodata="!showPage && !isLoading" :text="'您暂无' + lastDay + '营收数据'" />
</view>
</view>
</template>
<script>
import {
mapState
} from 'vuex';
import uCharts from '@/components/u-charts.js';
import shopCell from './components/listUnit.vue'
import AnhHead from './components/anhHead.vue'
import RankContent from './components/RankContent.vue'
import anhuiYestodayRevenueData from './components/anhuiYestodayRevenueData.js'
var rincanvas = {};
import request from '@/util/index.js'
export default {
data() {
const lastDay = this.$util.cutDate(new Date(), 'YYYY-MM-DD', -1)
const nowDay = this.$util.cutDate(new Date(), 'MM月DD日')
return {
showPage: false,
opacity: 0, // 背景颜色透明度
customBarH: this.CustomBar,
statusBarH: this.StatusBar,
isLoading: true,
theRequest: null,
sevenDate: null,
lastDay: lastDay, // 该页面的最近有效日期
nowDay: nowDay,
headMsg: null,
today: null, // 今日数据
regionList: null,
nowTab: 1,
regionShow1: true,
regionProgress: null,
tradeType: null,
areaProgress: null,
areaColors: ['#FFAC37', '#d8ece9', '#f7f5f6', '#b2b7e3', '#F4B27A', '#F3B1C9', '#e0e3f7', '#FFE886', '#f7f5f6', '#8E44AD', '#3498DB', '#E67E22', '#16A085', '#27AE60', '#2980B9', '#8E44AD', '#2C3E50', '#F39C12', '#D35400', '#C0392B'],
bayonetProgress: null,
modelProgress: null,
isup: true,
wechatPushSalesList: null, // 甘肃单品排行数据
currentMoney: ''
}
},
computed: {
...mapState({
'PushAuthority': (state) => state.userData.PushAuthority,
'ProvinceCode': (state) => state.userData.ProvinceCode,
}),
hasSeverpartIndexAuthority() {
let theRequest = this.theRequest
if (this.theRequest && theRequest.ProvinceCode && this.PushAuthority) {
return this.PushAuthority.some(n =>
n.ProvinceCode == theRequest.ProvinceCode && n.ShopAnalysisType == 1
)
}
return false
}
},
components: {
shopCell,
AnhHead,
RankContent
},
methods: {
toggleCard(isup) {
this.isup = !isup
this.$forceUpdate()
},
bindDateChange(e) { // 切换日期 加载选中日期的营收数据
// let nowDate = this.theRequest.time
let selectT = new Date(e.detail.value)
if (selectT <= new Date(this.lastDay)) {
this.theRequest.time = e.detail.value
this.theRequest.month = this.$util.cutDate(e.detail.value, 'YYYYMM')
this.sevenDate = [this.$util.cutDate(selectT, 'MM.DD', -13),
this.$util.cutDate(selectT, 'MM.DD', -7)]
uni.showLoading({
title: '正在加载...',
mask: true
})
this.initData()
// this.getTender()
this.todayAmount()
this.$forceUpdate()
}
},
toDetail(item, provinceId) { // 如果当前页面至存在一个初始化的省份编码 则不需要传入参数provinceId
let date = this.theRequest.time
let pcode = provinceId || this.theRequest.ProvinceCode
let severpartIndexPath = '/pages/everdayRenven/AnhuiServerpart?ServerpartIds=' + item.serverpart_Id +
'&time=' + date + '&ProvinceCode=' + pcode
let serverpartUploadPath = '/pages/everdayRenven/detail?id=' + item.serverpart_Id + '&time=' + date +
'&provinceId=' + pcode
// 是否有权限进入服务区营收分析页面
let canToSeverpartIndex = !provinceId ? this.hasSeverpartIndexAuthority : this.PushAuthority.some(n => {
return n.ProvinceCode == provinceId && n.ShopAnalysisType == 1
})
this.$util.toNextRoute('navigateTo', severpartIndexPath)
item.visited = true
this.$forceUpdate()
},
selectTab(name, index) {
this[name] = index
},
toggleRegion(item) {
item.show = !item.show ? true : false
this.$forceUpdate()
},
touchPie(e, id) {
rincanvas[id].showToolTip(e, {
format: function (item) {
return item.name + ':' + item.data
}
});
},
todayAmount() {
let _this = this
let theRequest = this.theRequest
this.$request.$get('getCurRevenue', {
pushProvinceCode: theRequest.ProvinceCode,
serverPartId: theRequest.GroupType == 1000 ? '' : theRequest.ServerpartIds
}).then(res => {
if (res.ResultCode != 100) return
let avrticket = (res.Data.TOTALTICKET != 0 && res.Data.TOTALPRICE != 0) ? res.Data.TOTALPRICE /
res.Data
.TOTALTICKET : 0
_this.today = {
timeMoney: this.$util.fmoney(res.Data.TOTALPRICE, 2),
totalTicketCount: res.Data.TOTALTICKET,
avrticketCount: this.$util.fmoney(avrticket, 2),
}
_this.$forceUpdate()
})
},
showPie(obj) {
let data = {
series: []
}
const ctx = uni.createCanvasContext(obj.id, this);
data.series = data.series.concat(obj.data)
// 针对不同图表使用不同配置
const isAreaChart = obj.id === 'areaCont'; // nowTab为3的图表
const legendConfig = isAreaChart ? {
show: true, // areaCont显示图例
padding: 5,
lineHeight: 11,
margin: 10,
position: 'right' // 图例显示在右侧
} : {
show: false, // 其他图表不显示图例
padding: 5,
lineHeight: 11,
margin: 0,
};
rincanvas[obj.id] = new uCharts({
// 小程序图表工具
// $this: this,
// canvasId: obj.id,
context: ctx,
color: obj.colors,
type: 'ring',
fontSize: 12,
padding: [15, 25, 25, 15],
legend: legendConfig,
background: '#FFFFFF',
pixelRatio: 1,
series: data.series,
animation: false,
width: uni.upx2px(686),
height: uni.upx2px(510),
dataLabel: !isAreaChart, // areaCont不显示引导线其他图表显示引导线
extra: {
ring: {
ringWidth: 40,
labelWidth: isAreaChart ? 0 : 15, // areaCont为0隐藏引导线其他图表为15显示引导线
border: true,
borderWidth: 1,
borderColor: '#fff'
}
},
});
},
getDetail(obj) {
console.log('obj', obj)
let _this = this
this.$request.$webGet('CommercialApi/Revenue/GetServerpartEndAccountList', {
Serverpart_ID: obj.ServerpartIds,
pushProvinceCode: obj.ProvinceCode,
Statistics_Date: obj.time,
}).then(res => {
if (res.Result_Code != 100) return
res.Result_Data.ShopEndaccountList.map(n => {
n.show = false
n.detail = this.getListDetail(n)
})
_this.regionList = res.Result_Data.ShopEndaccountList
console.log('_this.regionList', _this.regionList)
})
},
getListDetail(data) {
let arr = []
let keyJson = {
SHOWMORE_SIGN: {
1: '【长款】',
2: '【异常长款】'
}, // 长款
SHOWLESS_SIGN: {
1: '【短款】',
2: '【异常短款】'
}, // 短款
SHOWABNORMAL_SIGN: {
1: '【异常校验】'
}, // 异常日结
SHOWSCAN_SIGN: {
1: '【扫】'
}, // 扫码上传
SHOWSSUPPLY_SIGN: {
1: '【补】'
}, // 账期补录
SHOWCHECK_SIGN: {
1: '【稽核检查】'
}, // 稽核检查
INTERFACE_SIGN: {
1: '【接口传输】'
}, // 接口传输
}
var keyCode = ['SHOWABNORMAL_SIGN', 'SHOWCHECK_SIGN', 'SHOWMORE_SIGN', 'SHOWLESS_SIGN', 'SHOWSCAN_SIGN',
'SHOWSSUPPLY_SIGN', 'INTERFACE_SIGN'
]
keyCode.map(n => {
if (keyJson[n][data[n]]) arr.push(keyJson[n][data[n]])
})
return arr
},
toggleShow(i) {
let item = this.regionList[i]
item.show = !item.show
this.$forceUpdate()
},
defaultMsg() {
let option = null
let _this = this
if (this.PushAuthority && this.PushAuthority.length > 1) {
option = this.PushAuthority.find(n => n.ProvinceCode === _this.ProvinceCode)
} else {
option = this.PushAuthority[0]
}
return {
...option
}
},
async initData() { // 初始化营收数据
let _this = this
console.log('this.theRequest1', this.theRequest)
this.theRequest.GroupType = 1000
this.theRequest.ServerpartIds = ''
const [reginList, totalData, busniessTypePie, busniessTradePie, busniessAreaPie, bayonetPie] =
await anhuiYestodayRevenueData.getData(this.theRequest) // 获取实时数据
if (this.theRequest.GroupType !== 1010) {
console.log('reginList', reginList)
this.regionList = reginList // 营收上传列表 reginListModel[]
}
// 组合及格式化 头部卡片总营收数据。
totalData.tickave = totalData.ticketCount > 0 ? this.$util.fmoney(
totalData.cashPay / totalData.ticketCount, 2) : 0
totalData.countave = totalData.totalCount > 0 ? this.$util.fmoney(
totalData.cashPay / totalData.totalCount, 2) : 0
totalData.totalMoneyShow = this.$util.fmoney(totalData.cashPay) // 营收总数据格式化
totalData.dayOfShow = this.$util.cutDate(this.theRequest.time, 'MM月DD日') // 当前日期
totalData.budgetamoutShow = totalData.budgetAmount ?
_this.$util.fmoney(totalData.budgetAmount) : 0.00 // 预算总营收
busniessTypePie.forEach((n, i) => {
if (n.name === '自营') {
// 预算和实际差额
totalData.diffBudgetTotal = Math.abs(totalData.budgetAmount - n.data)
// 预算和实际增长额比例
totalData.diffBili = totalData.budgetAmount > 0 ?
this.$util.fmoney((totalData.diffBudgetTotal /
totalData.budgetAmount) * 100, 2) : '100'
}
});
this.headMsg = totalData
// 饼图分析及数据条形分析
const [progressList, pieList] = this.getProgressData(busniessTypePie, totalData.cashPay)
this.modelProgress = progressList
// 经营类型分析
var colors1 = ['#FFAC37', '#6B75B8'];
// console.log(pieList)
this.showPie({
id: 'modelCont',
data: pieList,
colors: colors1,
});
// 经营业态
// 饼图分析及数据条形分析
const [tprogressList, tpieList] = this.getProgressData(busniessTradePie, totalData.cashPay)
this.regionProgress = tprogressList
// 经营类型分析
var colors2 = ['#5E67B4', '#4E5699', '#75B7AD', '#AFB7E6'];
this.showPie({
id: 'businessCont',
data: tpieList,
colors: colors2,
});
// 饼图分析及数据条形分析
const [aprogressList, apieList] = this.getProgressData(busniessAreaPie, totalData.cashPay)
this.areaProgress = aprogressList
// 区域营收分析
this.showPie({
id: 'areaCont',
data: apieList,
colors: this.areaColors,
});
// 安徽省本级显示的内容
if (this.theRequest.GroupType == 1000 && this.theRequest.ProvinceCode == 340000) {
// 显示片区车流量数据分析
const [bayonetList] = this.getBayonetData(bayonetPie)
this.bayonetProgress = bayonetList
}
if (reginList.length) {
this.showPage = true
}
this.isLoading = false
uni.hideLoading()
},
getProgressData(data, total) {
var _data1 = [];
var _data2 = [];
let _this = this
data.forEach((n, i) => {
_data1.push({
...n,
name: n.name.split('管理单元')[0],
textColor: '#999',
formatter: function (arg) {
if (typeof arg === 'number') {
return [n.name, (arg * 100).toFixed(2) + '%']
} else {
return [arg.name, (arg._proportion_ * 100).toFixed(2) + '%']
}
}
});
_data2.push({
name: n.name,
num: n.data,
data: _this.$util.fmoney(n.data, 2), //+Number(data2[n[0]])
bili: _this.$util.fmoney((n.data / total) * 100, 2)
});
});
_data1.sort(function (a, b) {
return b.data - a.data
})
_data2.sort(function (a, b) {
return b.num - a.num
})
return [_data2, _data1];
},
getBayonetData(data) {
var _data1 = [];
let _this = this
data.forEach((n, i) => {
var childData = [];
n.spList.forEach((m, i) => {
// 获取服务区各个方位的入区信息
var _list = [];
m.regionList.forEach((o, i) => {
_list.push({
name: o.name,
data: o.Vehicle_Count,
flow: o.SectionFlow_Count,
bili: o.SectionFlow_Count == 0 ? 100 : _this.$util.fmoney(
(o.Vehicle_Count / o.SectionFlow_Count) * 100, 2),
MinVehicle_Count: o.MinVehicle_Count,
MediumVehicle_Count: o.MediumVehicle_Count,
LargeVehicle_Count: o.LargeVehicle_Count
});
});
_list.sort(function (a, b) {
return b.bili - a.bili
})
childData.push({
name: m.name,
data: m.Vehicle_Count, //+Number(data2[n[0]])
flow: m.SectionFlow_Count,
bili: m.SectionFlow_Count == 0 ? 0 : _this.$util.fmoney(
(m.Vehicle_Count / m.SectionFlow_Count) * 100, 2),
list: _list
});
});
childData.sort(function (a, b) {
return b.bili - a.bili
})
_data1.push({
name: n.name,
index: n.index,
list: childData
});
});
_data1.sort(function (a, b) {
return a.index - b.index
})
return [_data1];
},
async getRankContent() { // 甘肃需要单品排行显示
const {
ProvinceCode,
time
} = this.theRequest
const data = await this.$request.$webGet('CommercialApi/Revenue/GetWechatPushSalesList', {
pushProvinceCode: ProvinceCode,
Statistics_Date: time
})
if (data.Result_Code === 100 && data.Result_Data.TotalCount > 0) {
this.wechatPushSalesList = {}
data.Result_Data.List.forEach(n => {
this.wechatPushSalesList[n.Data_Type] = n.GoodsList
})
} else {
this.wechatPushSalesList = {}
}
this.$forceUpdate()
},
// 实时营收
handleRealRevenue() {
const {
ProvinceCode,
} = this.theRequest
const date = new Date()
let y = date.getFullYear()
let m = date.getMonth() + 1
let d = date.getDate()
if (m < 10) {
m = '0' + m
}
if (d < 10) {
d = '0' + d
}
let req = {
pushProvinceCode: ProvinceCode,
StatisticsDate: `${y}-${m}-${d}`
}
request.$webGet('CommercialApi/Revenue/GetCurRevenue', req).then(res => {
console.log('res222222', res)
this.currentMoney = this.$util.fmoney(res.Result_Data.CurRevenueAmount, 2)
})
},
},
onUnload() {
this.$util.addUserBehavior()
},
onPageScroll(options) {
this.opacity = (options.scrollTop - 30) / 68
},
onLoad(option) {
uni.showLoading({
title: '正在加载...'
})
if (option.ProvinceCode) { // 从推送进入
this.theRequest = option
option.time = this.$util.cutDate(option.time, 'YYYY-MM-DD')
option.month = this.$util.cutDate(option.time, 'YYYYMM')
this.initData()
this.handleRealRevenue()
} else { // 默认
if (this.PushAuthority.length > 0) {
console.log('11111')
this.theRequest = this.defaultMsg() || {}
let storeTime = uni.getStorageSync('lastDay')
if (storeTime) {
this.theRequest.time = storeTime
this.theRequest.month = this.$util.cutDate(storeTime, 'YYYYMM')
} else {
this.theRequest.time = this.lastDay
this.theRequest.month = this.$util.cutDate(this.lastDay, 'YYYYMM')
}
this.initData()
this.handleRealRevenue()
} else {
uni.hideLoading()
this.theRequest = null
this.isLoading = false
this.showPage = false
this.opacity = 1
}
}
this.nowTab = this.theRequest.ProvinceCode == 340000 ? 1 : 2
this.todayAmount()
if (this.theRequest.GroupType == 1010) {
this.getDetail(this.theRequest)
}
// 若省份为甘肃,则加载甘肃单品排行
if (this.theRequest.ProvinceCode == "620000" || this.theRequest.ProvinceCode == "530000") {
this.getRankContent()
}
},
}
</script>
<style lang="scss" scoped>
.page-body {
background-color: #f8f9fa;
position: relative;
box-sizing: border-box;
min-height: 100vh;
padding-bottom: env(safe-area-inset-bottom);
}
.uni-flex-column {
flex-direction: column;
}
.justify-between {
justify-content: space-between;
}
.justify-around {
justify-content: space-around;
}
.uni-icon-arrowright {
font-size: 32rpx;
color: #5A5A5A;
}
.uni-icon-arrowright.active {
transform: rotate(90deg);
}
.ct01 {
color: #383838;
}
.strong-text {
font-weight: 700;
}
.ct-red {
color: #ff4757 !important;
font-weight: 600;
}
.new-content {
background: url('https://eshangtech.com/ShopICO/ahyd-BID/revenue/banner.png') no-repeat bottom left;
height: 383rpx;
background-size: 100%;
color: #fff;
box-sizing: border-box;
padding-top: 20rpx;
}
.new-content .text-title {
flex: 1;
text-align: center;
font-weight: 600;
}
.uni-icon-arrowleft {
font-size: 38rpx;
padding: 8rpx 16rpx;
}
.page-title {
display: flex;
align-items: center;
padding-right: 70rpx;
width: 100%;
color: #fff;
background-color: #3b64a3;
}
.page-title .uni-icon-arrowleft,
.page-title .uni-icon-arrowleft:before {
color: #fff;
}
.new-content .header-card {
background-size: contain;
background-repeat: no-repeat;
background-position: center right;
padding: 0 30rpx;
color: #BED4F4;
padding-top: 8rpx;
position: relative;
}
.head-log {
position: absolute;
right: 12rpx;
top: 0rpx;
width: 376rpx;
height: 198rpx;
}
.new-content .top-number {
padding-top: 28rpx;
font-size: 76rpx;
padding-bottom: 16rpx;
color: #fff;
padding-left: 4rpx;
font-family: 'Bahnschrift Regular';
letter-spacing: 2rpx;
line-height: 1.1;
transition: all 1s;
}
.new-content .header-today-info {
align-items: baseline;
}
.new-content .header-today-info text {
font-family: 'Bahnschrift Regular';
font-size: 30rpx;
}
.ml10 {
margin-left: 20rpx;
}
.new-content .header-today-info text.fs12,
text.fs12 {
font-size: 24rpx;
}
.ml-135 {
margin-left: 135rpx;
}
.top-number view {
line-height: 1.2;
}
.heade-text {
text-align: right;
line-height: 1;
letter-spacing: 0;
color: #BED4F4;
font-family: 'Bahnschrift Regular';
display: flex;
align-items: center;
}
/* 营收汇总 数据概览卡片 */
.revenue-card-cont {
padding: 6rpx 0 32rpx 0;
border-radius: 12rpx;
margin: 0 32rpx;
box-shadow: 0rpx 0rpx 6rpx 0px rgba(224, 224, 224, 0.54);
}
.head-cost-text {
color: #BED4F4;
font-size: 28rpx;
}
.top-revenue-card {
padding: 16rpx 30rpx 6rpx 30rpx;
font-family: 'Bahnschrift Regular';
color: #D7B89A;
align-items: flex-end;
}
.top-revenue-card .top-number {
font-size: 56rpx;
color: #D0AC8B;
line-height: 1;
}
.top-revenue-card .upLoad-text {
font-size: 32rpx;
}
.check-unit {
font-size: 24rpx;
margin-top: 16rpx;
flex: 1;
text-align: center;
}
.check-price-color {
font-size: 32rpx;
color: #868686;
line-height: 1.2;
font-family: 'Bahnschrift Regular';
}
.check-price-color text {
font-size: 22rpx;
}
/* end */
.modle-title {
padding: 0 32rpx 24rpx 32rpx;
font-size: 32rpx;
font-weight: 600;
color: #333;
display: flex;
align-items: center;
margin-top: 32rpx;
box-sizing: border-box;
image {
width: 40rpx;
height: 40rpx;
margin-right: 12rpx;
}
}
.modle-title .uni-icon-arrowdown {
font-size: 24rpx;
}
.modle-title picker {
color: #000000;
padding-right: 24rpx;
position: relative;
width: 164rpx;
}
.modle-title picker .revenue-date:before {
content: '';
position: absolute;
width: 0rpx;
height: 0rpx;
border: 0rpx;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
border-top: 12rpx solid #000;
right: 22rpx;
top: 22rpx;
display: block;
border-radius: 6rpx;
}
.upload-count {
font-family: 'DIN Alternate', 'Bahnschrift', sans-serif;
font-size: 32rpx;
font-weight: 600;
color: #27B25F;
margin-left: 16rpx;
margin-right: 36rpx;
}
.region-title {
padding: 20rpx 60rpx 20rpx 80rpx;
position: relative;
font-size: 30rpx;
font-weight: bolder;
}
.region-title:before {
content: '';
position: absolute;
width: 20rpx;
height: 20rpx;
background: url(/static/images/revenue/select.png) no-repeat center;
background-size: contain;
left: 40rpx;
top: 36rpx;
}
.active.region-title:before {
background: url(/static/images/revenue/select_active.png) no-repeat center;
background-size: contain;
}
/*日结上传*/
.region-cell {
display: flex;
align-items: center;
justify-content: space-between;
padding: 32rpx 24rpx;
background-color: #fff;
margin-bottom: 12rpx;
border-radius: 12rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
border: 1rpx solid #f5f5f5;
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
box-shadow: 0 4rpx 20rpx rgba(39, 178, 95, 0.15);
}
}
.region-cell .region-cell-unit {
flex: 2;
display: flex;
flex-direction: column;
color: #666;
font-size: 28rpx;
line-height: 1.4;
text-align: right;
.strong-text {
font-size: 32rpx;
font-weight: 600;
color: #333;
font-family: 'DIN Alternate', 'Bahnschrift', sans-serif;
}
}
.region-cell .region-cell-unit:nth-child(1) {
flex: 3;
text-align: left;
font-size: 30rpx;
font-weight: 600;
color: #333;
}
.region-cell .region-cell-unit:nth-child(3) {
line-height: 1.2;
font-size: 26rpx;
font-weight: 500;
padding: 8rpx 12rpx;
background-color: #f8f9fa;
border-radius: 8rpx;
min-width: 80rpx;
text-align: center;
}
.region-cell-image {
width: 48rpx;
display: flex;
align-items: center;
justify-content: center;
height: 48rpx;
.uni-icon-arrowright {
font-size: 28rpx;
color: #999;
transition: all 0.3s ease;
&.active {
transform: rotate(90deg);
color: #27B25F;
}
}
}
.region-cell image {
width: 14rpx;
height: 23rpx;
}
/*日结上传服务区*/
.region-cell-area {
max-height: 600rpx;
overflow: auto;
-webkit-overflow-scrolling: touch;
background-color: #f8f9fa;
border-radius: 12rpx;
margin: 12rpx 0 0 0;
padding: 16rpx 0;
}
.region-cell-area li.visited view:first-child {
color: #007AFF;
}
.region-cell-area li:after {
content: '';
font-size: 24rpx;
color: #999;
display: block;
position: absolute;
right: 16rpx;
top: 50%;
transform: translateY(-50%);
}
.region-cell-area li:nth-child(2n+1) {
background-color: #fff;
}
.region-cell-area li:nth-child(2n+1):before {
content: '';
background: linear-gradient(135deg, #27B25F, #4CCC7F);
width: 8rpx;
height: 8rpx;
border-radius: 50%;
display: block;
position: absolute;
left: 20rpx;
top: 50%;
transform: translateY(-50%);
}
.region-cell-area li:nth-child(2n):before {
content: '';
background: linear-gradient(135deg, #ff9f43, #ff6b6b);
width: 8rpx;
height: 8rpx;
border-radius: 50%;
display: block;
position: absolute;
left: 20rpx;
top: 50%;
transform: translateY(-50%);
}
.region-cell-area li {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 24rpx 20rpx 48rpx;
position: relative;
text-align: right;
color: #333;
background-color: #fff;
margin: 8rpx 12rpx;
border-radius: 8rpx;
border: 1rpx solid #f0f0f0;
transition: all 0.2s ease;
&:active {
background-color: #f8f9fa;
transform: scale(0.99);
}
}
.region-cell-area li>div {
flex: 2;
font-size: 22rpx;
}
.region-cell-area li>div:nth-child(1) {
flex: 3;
text-align: left;
}
/*车流量分析*/
.bayonet-cell-area {
/* display: none; */
max-height: 460rpx;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.bayonet-cell-area li {
width: 100%;
}
.bayonet-cell-area li .server {
width: 30%;
display: inline-block;
text-align: left;
padding-left: 15rpx;
}
.bayonet-cell-area li .type {
width: 35%;
display: inline-block;
text-align: center;
}
.bayonet-cell-area li .carType {
width: 30%;
display: inline-block;
text-align: right;
}
.bayonet-cell-area li:nth-child(2n+1):before {
content: '';
background-color: #5596F9;
width: 8rpx;
height: 8rpx;
border-radius: 8rpx;
display: block;
position: absolute;
left: 0;
top: 40%;
}
.bayonet-cell-area li:nth-child(2n):before {
content: '';
background-color: #FE6D67;
width: 8rpx;
height: 8rpx;
border-radius: 8rpx;
display: block;
position: absolute;
left: 0;
top: 40%;
}
.bayonet-cell-area li {
width: 100%;
/*display: flex;*/
/*align-items: center;*/
/*justify-content: space-around;*/
position: relative;
}
.bayonet-cell-area li>div {
flex: 2;
}
.bayonet-cell-area li>div:nth-child(1) {
flex: 3;
text-align: left;
}
.bayonet-c-list {
padding: 16rpx 32rpx;
width: 100%;
position: relative;
}
.bayonet-c-list div:before {
content: '';
background: url(/static/images/authority/fwq.png) no-repeat center;
width: 35rpx;
height: 35rpx;
display: inline-block;
position: absolute;
left: 0;
top: 7px;
}
.modle-title image {
max-width: 36rpx;
max-height: 36rpx;
}
.line-tab-unit {
margin-top: 20rpx;
/* width: 60rpx; */
height: 44rpx;
font-size: 28rpx;
color: #A9A9A9;
background: #ececec;
border-radius: 8rpx;
text-align: center;
line-height: 44rpx;
margin-right: 32rpx;
padding: 0 10rpx;
font-size: 22rpx;
}
.line-tab-unit.active {
background-color: #667ED5;
color: #fff;
}
.revenue-line-box {
background-color: #fff;
margin: 0 16rpx;
border-radius: 20rpx;
padding: 34rpx 16rpx 34rpx 16rpx;
box-shadow: 1rpx 0rpx 6rpx 0px rgba(224, 224, 224, 0.54);
}
.revenue-line-box+.revenue-line-box {
margin-top: 38rpx;
}
.revenue-line-data {
width: 216rpx;
height: 144rpx;
background-color: #F8F8F8;
border-radius: 12rpx;
color: #A5A5A5;
font-size: 24rpx;
text-align: center;
padding-top: 20rpx;
border: 2rpx solid #F8F8F8;
box-sizing: border-box;
}
.revenue-line-data+.revenue-line-data {
margin-left: 24rpx;
}
.revenue-line-data p:last-child {
font-size: 40rpx;
font-family: 'Bahnschrift Regular';
line-height: 1.2;
}
.revenue-line-data.active {
border: 2rpx solid #889DED;
background-color: #f1f3fb;
color: #667ED5;
}
.revenue-line-box .text-title {
color: #9498A4;
font-size: 24rpx;
margin-top: 38rpx;
}
.revenue-line-box .up-text-title {
color: #6eb92b;
font-family: 'Bahnschrift Regular';
font-size: 36rpx;
line-height: 1.5;
}
.up-text-title:after {
content: "";
margin-left: 12rpx;
width: 20rpx;
height: 22rpx;
display: inline-block;
background: url('/static/images/revenue/up-arrow.png') no-repeat center;
background-size: contain;
}
.text-week {
color: #C2C2C2;
margin-left: 32rpx;
}
.down-text-title:after {
content: "";
margin-left: 12rpx;
width: 20rpx;
height: 22rpx;
display: inline-block;
background: url('/static/images/revenue/down-arrow.png') no-repeat center;
background-size: contain;
}
.revenue-line-box .down-text-title {
color: #F07878;
font-family: 'Bahnschrift Regular';
font-size: 36rpx;
line-height: 1.5;
}
.revenue-line-box .title {
color: #000;
font-size: 28rpx;
font-weight: bolder;
}
.revenue-line-box canvas.operation-content {
height: 350rpx;
width: 686rpx;
margin: 0 auto 0 auto;
background-color: #fff;
}
/*区域营收占比*/
/* //.operation-bgfc {
// background-color: #FCFCFC;
// padding-bottom: 32rpx;
//} */
.box-operation {
background-color: #fff;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
margin: 0 0 24rpx 0;
border-radius: 16rpx;
overflow: hidden;
border: 1rpx solid #f0f0f0;
}
.operation-tab-box {
background: #f8f9fa;
border-radius: 0;
display: flex;
align-items: center;
text-align: center;
overflow: hidden;
margin: 0;
}
.operation-tab-box .operation-tab-unit {
color: #666;
flex: 1;
height: 88rpx;
line-height: 88rpx;
position: relative;
font-size: 28rpx;
font-weight: 500;
transition: all 0.3s ease;
cursor: pointer;
}
.operation-tab-box .operation-tab-unit.active {
background: linear-gradient(135deg, #27B25F, #4CCC7F);
color: #fff;
font-weight: 600;
position: relative;
z-index: 2;
box-shadow: 0 4rpx 12rpx rgba(39, 178, 95, 0.3);
border-radius: 8rpx;
margin: 4rpx;
height: 80rpx;
line-height: 80rpx;
}
.operation-tab-box .operation-tab-unit.active:after {
content: none;
}
.operation-tab-box .operation-tab-unit:after {
content: none;
}
.operation-content-box {
width: 100%;
overflow: hidden;
padding: 24rpx;
background-color: #fff;
}
canvas.operation-content {
height: 400rpx;
width: 100%;
max-width: 600rpx;
margin: 0 auto;
background-color: #fff;
border-radius: 8rpx;
}
.operation-c-list {
padding: 20rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
}
.operation-cl-unit {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
color: #333;
margin-bottom: 8rpx;
text:first-child {
font-weight: 600;
color: #27B25F;
}
text:last-child {
font-weight: 600;
font-family: 'DIN Alternate', 'Bahnschrift', sans-serif;
}
}
.operation-cl-unit1 {
width: 100%;
font-size: 26rpx;
display: flex;
justify-content: space-between;
}
.operation-cl-unit1 .server {
width: 30%;
display: inline-block;
text-align: left;
padding-left: 30rpx;
}
.operation-cl-unit1 .type {
width: 40%;
display: inline-block;
text-align: left;
}
.operation-cl-unit1 .carType {
width: 30%;
display: inline-block;
text-align: center;
}
.operation-c-list .progress {
width: 100%;
height: 8rpx;
background-color: #f0f0f0;
border-radius: 4rpx;
margin-top: 12rpx;
overflow: hidden;
}
.operation-c-list .progress .bgO {
height: 100%;
border-radius: 4rpx;
background: linear-gradient(90deg, #27B25F, #4CCC7F);
transition: width 0.6s ease;
}
/*排行*/
.ranking-tab-box {
margin: 20rpx 32rpx;
border: 2rpx solid #565656;
border-radius: 8rpx;
display: flex;
align-items: center;
text-align: center;
}
.ranking-tab-box .ranking-tab-unit {
color: #565656;
flex: 1;
height: 64rpx;
line-height: 60rpx;
}
.ranking-tab-box .ranking-tab-unit.active {
background-color: #565656;
color: #fff
}
.ranking-tab-box .ranking-tab-unit+.ranking-tab-unit {
border-left: 2rpx solid #565656;
}
.ranking-content {
/* display: none; */
min-height: 160rpx;
}
.ranking-content .ranking-list {
display: flex;
align-items: center;
color: #000;
padding: 24rpx 32rpx;
}
.ranking-content .rank-index {
width: 72rpx;
height: 72rpx;
text-align: center;
line-height: 72rpx;
font-size: 30rpx;
font-weight: bolder;
margin-right: 32rpx;
}
.ranking-content .ranking-list:nth-child(1) .rank-index {
background: url('https://eshangtech.com/ShopICO/ahyd-BID/revenue/top1.png') no-repeat center;
background-size: contain;
font-size: 0;
}
.ranking-content .ranking-list:nth-child(2) .rank-index {
background: url('https://eshangtech.com/ShopICO/ahyd-BID/revenue/top1.png') no-repeat center;
background-size: contain;
font-size: 0;
}
.ranking-content .ranking-list:nth-child(3) .rank-index {
background: url('https://eshangtech.com/ShopICO/ahyd-BID/revenue/top3.png') no-repeat center;
background-size: contain;
font-size: 0;
}
.ranking-content .ranking-list-unit {
font-size: 28rpx;
flex: 1;
}
.ranking-content .ranking-unit-info {
/* margin-top: 16rpx; */
display: flex;
align-items: center;
/* font-size: .13rem; */
}
.ranking-content .ranking-unit-info text {
flex: 2;
color: #929292;
}
.ranking-content .ranking-unit-info text:nth-child(2) {
flex: 3;
}
.ranking-content .ranking-unit-info text:nth-child(2n) {
color: #000
}
.ranking-ico {
width: 72rpx;
height: 72rpx;
}
// 新增主内容区域样式
.main-content {
background-color: #fff;
margin: 0;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
border: 1rpx solid #f0f0f0;
margin-bottom: 24rpx;
}
/* 现代化页面重设计样式 */
.section-header {
padding: 32rpx 24rpx 24rpx;
border-bottom: 2rpx solid #f1f3f4;
display: flex;
align-items: center;
justify-content: space-between;
background: #f8f9fa;
}
.section-title {
display: flex;
align-items: center;
}
.section-icon {
margin-right: 12rpx;
}
.icon-emoji {
font-size: 32rpx;
}
.section-text {
font-size: 28rpx;
font-weight: 700;
color: #2c3e50;
}
.section-badge {
background: #27B25F;
color: white;
font-size: 22rpx;
padding: 8rpx 16rpx;
border-radius: 20rpx;
font-weight: 500;
}
/* 分析容器 */
.analysis-container {
background: #fff;
}
/* 现代化标签页 */
.modern-tabs {
display: flex;
background: #f8f9fa;
padding: 8rpx;
margin: 0 24rpx 24rpx;
border-radius: 16rpx;
}
.tab-item {
flex: 1;
padding: 24rpx 16rpx;
text-align: center;
border-radius: 12rpx;
transition: all 0.3s ease;
cursor: pointer;
border: none;
background: transparent;
color: #666;
margin: 0 8rpx;
}
.tab-item.active {
background: #27B25F;
color: white;
box-shadow: 0 4rpx 16rpx rgba(39, 178, 95, 0.2);
}
.tab-icon {
font-size: 32rpx;
margin-bottom: 8rpx;
line-height: 1;
}
.tab-label {
font-size: 26rpx;
font-weight: 500;
line-height: 1.2;
}
/* 内容包装器 */
.content-wrapper {
padding: 0 24rpx 32rpx;
}
/* 图表区域 */
.chart-section {
margin-bottom: 32rpx;
}
.chart-container {
background: #f8f9fa;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04);
border: 1rpx solid rgba(0, 0, 0, 0.04);
}
.modern-chart {
width: 100%;
height: 500rpx;
border-radius: 8rpx;
background: white;
}
/* 图表和图例的容器 - 左右布局 */
.chart-with-legend {
display: flex;
gap: 20rpx;
align-items: flex-start;
}
.chart-container-side {
background: #f8f9fa;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04);
border: 1rpx solid rgba(0, 0, 0, 0.04);
flex: 2;
min-width: 0;
}
.modern-chart-side {
width: 100%;
height: 500rpx;
border-radius: 8rpx;
background: white;
}
/* 右侧图例容器 */
.legend-container-right {
flex: 1;
background: #f8f9fa;
border-radius: 16rpx;
padding: 20rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04);
border: 1rpx solid rgba(0, 0, 0, 0.04);
height: 500rpx;
display: flex;
flex-direction: column;
}
.legend-title {
font-size: 26rpx;
font-weight: 600;
color: #2c3e50;
margin-bottom: 20rpx;
padding-bottom: 10rpx;
border-bottom: 1rpx solid #e9ecef;
}
.legend-items {
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.legend-item-side {
display: flex;
align-items: center;
padding: 16rpx 0;
margin-bottom: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
transition: all 0.3s ease;
}
.legend-item-side:last-child {
margin-bottom: 0;
border-bottom: none;
}
.legend-item-side:hover {
background: rgba(39, 178, 95, 0.05);
transform: translateX(4rpx);
}
.legend-color-side {
width: 24rpx;
height: 24rpx;
border-radius: 6rpx;
margin-right: 16rpx;
flex-shrink: 0;
border: 2rpx solid #fff;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.legend-info-side {
flex: 1;
min-width: 0;
}
.legend-name-side {
font-size: 24rpx;
font-weight: 600;
color: #2c3e50;
margin-bottom: 6rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.legend-stats-side {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12rpx;
}
.legend-percentage-side {
font-size: 22rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.legend-amount-side {
font-size: 20rpx;
color: #666;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 120rpx;
text-align: right;
}
/* 紧凑版数据卡片 */
.data-cards-compact {
display: flex;
flex-wrap: wrap;
margin: -4rpx;
margin-top: 16rpx;
}
.data-card-compact {
background: white;
border-radius: 8rpx;
padding: 12rpx 16rpx;
box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.04);
border: 1rpx solid rgba(0, 0, 0, 0.04);
display: flex;
align-items: center;
gap: 16rpx;
width: calc(50% - 8rpx);
margin: 4rpx;
}
.category-name-compact {
font-size: 22rpx;
font-weight: 600;
color: #2c3e50;
min-width: 80rpx;
}
.percentage-compact {
font-size: 20rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
min-width: 60rpx;
text-align: right;
}
.amount-compact {
font-size: 22rpx;
font-weight: 700;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnsicht', monospace;
min-width: 100rpx;
text-align: right;
}
.progress-bar-compact {
flex: 1;
height: 6rpx;
background-color: #f0f0f0;
border-radius: 3rpx;
overflow: hidden;
min-width: 60rpx;
}
.progress-fill-compact {
height: 100%;
border-radius: 3rpx;
background: #27B25F;
transition: width 0.6s ease;
}
/* 数据卡片布局 - 使用flex替代grid */
.data-cards {
display: flex;
flex-wrap: wrap;
margin: -8rpx;
}
.data-card {
background: white;
border-radius: 12rpx;
padding: 24rpx 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
border: 1rpx solid rgba(0, 0, 0, 0.04);
position: relative;
overflow: hidden;
width: calc(50% - 16rpx);
margin: 8rpx;
box-sizing: border-box;
}
.data-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4rpx;
background: #27B25F;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16rpx;
}
.category-name {
font-size: 26rpx;
font-weight: 600;
color: #2c3e50;
}
.percentage {
font-size: 24rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.amount {
font-size: 32rpx;
font-weight: 700;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
margin-bottom: 12rpx;
line-height: 1.1;
}
.progress-bar {
width: 100%;
height: 8rpx;
background-color: #f0f0f0;
border-radius: 4rpx;
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: 4rpx;
background: #27B25F;
transition: width 0.6s ease;
}
/* 流量分析区域 */
.traffic-analysis {
margin-bottom: 32rpx;
}
.traffic-regions {
padding: 0;
}
.region-section {
margin-bottom: 32rpx;
}
.region-title {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 2rpx solid #f1f3f4;
margin-bottom: 20rpx;
}
.region-icon {
font-size: 28rpx;
margin-right: 12rpx;
}
.region-name {
font-size: 30rpx;
font-weight: 600;
color: #2c3e50;
}
.service-areas {
display: flex;
flex-wrap: wrap;
margin: -10rpx;
}
.service-area-card {
background: #f8f9fa;
border-radius: 12rpx;
padding: 24rpx 20rpx;
border: 1rpx solid rgba(0, 0, 0, 0.04);
width: calc(50% - 20rpx);
margin: 10rpx;
box-sizing: border-box;
}
.area-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16rpx;
}
.area-name {
font-size: 28rpx;
font-weight: 600;
color: #2c3e50;
}
.flow-ratio {
font-size: 24rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.flow-stats {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16rpx;
padding: 16rpx;
background: white;
border-radius: 8rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
}
.stat-item {
text-align: center;
flex: 1;
}
.stat-label {
font-size: 22rpx;
color: #6c757d;
margin-bottom: 4rpx;
}
.stat-value {
font-size: 28rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.stat-divider {
width: 1rpx;
height: 40rpx;
background: #e9ecef;
margin: 0 16rpx;
}
.vehicle-breakdown {
margin-top: 16rpx;
}
.vehicle-item {
background: white;
border-radius: 8rpx;
padding: 16rpx;
margin-bottom: 12rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
}
.vehicle-item:last-child {
margin-bottom: 0;
}
.direction-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12rpx;
}
.direction-name {
font-size: 26rpx;
font-weight: 600;
color: #2c3e50;
}
.direction-ratio {
font-size: 22rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.vehicle-types {
display: flex;
gap: 16rpx;
}
.vehicle-type {
font-size: 22rpx;
color: #6c757d;
background: #f8f9fa;
padding: 6rpx 12rpx;
border-radius: 16rpx;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
/* 上传数据区域 */
.upload-section {
background: white;
border-radius: 16rpx;
padding: 32rpx 24rpx 0;
margin-bottom: 32rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
border: 1rpx solid rgba(0, 0, 0, 0.04);
}
.upload-header {
display: flex;
align-items: center;
justify-content: space-between;
// margin-bottom: 24rpx;
padding-bottom: 16rpx;
// border-bottom: 2rpx solid #f1f3f4;
}
.upload-title {
display: flex;
align-items: center;
}
.upload-icon {
font-size: 28rpx;
margin-right: 12rpx;
}
.upload-text {
font-size: 32rpx;
font-weight: 600;
color: #2c3e50;
}
.upload-summary {
display: flex;
align-items: center;
gap: 12rpx;
}
.summary-label {
font-size: 24rpx;
color: #6c757d;
}
.summary-value {
font-size: 28rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
/* 服务列表 */
.service-list {
background: white;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 32rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
border: 1rpx solid rgba(0, 0, 0, 0.04);
}
.service-card {
background: #f8f9fa;
border-radius: 12rpx;
padding: 24rpx 20rpx;
margin-bottom: 16rpx;
border: 1rpx solid rgba(0, 0, 0, 0.04);
position: relative;
overflow: hidden;
}
.service-card:last-child {
margin-bottom: 0;
}
.service-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4rpx;
background: #27B25F;
}
.service-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16rpx;
}
.service-info {
flex: 1;
}
.service-name {
font-size: 30rpx;
font-weight: 600;
color: #2c3e50;
margin-bottom: 8rpx;
}
.service-revenue {
font-size: 32rpx;
font-weight: 700;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.service-status {
text-align: right;
}
.upload-rate {
font-size: 28rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
margin-bottom: 4rpx;
}
.upload-rate.warning {
color: #ff9f43;
}
.upload-fraction {
font-size: 22rpx;
color: #6c757d;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.upload-fraction.incomplete {
color: #ff4757;
}
.service-indicator {
display: flex;
align-items: center;
gap: 8rpx;
margin-top: 16rpx;
}
.status-dot {
width: 8rpx;
height: 8rpx;
border-radius: 50%;
background: #ff4757;
}
.status-dot.complete {
background: #27B25F;
}
.arrow-icon {
font-size: 24rpx;
color: #999;
font-weight: 600;
}
/* 区域列表 */
.region-list {
background: white;
border-radius: 16rpx;
padding: 24rpx;
// margin-bottom: 32rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
border: 1rpx solid rgba(0, 0, 0, 0.04);
}
.region-card {
background: #f8f9fa;
border-radius: 12rpx;
margin-bottom: 16rpx;
border: 1rpx solid rgba(0, 0, 0, 0.04);
overflow: hidden;
}
.region-card:last-child {
margin-bottom: 0;
}
.region-main {
padding: 24rpx 20rpx;
position: relative;
}
.region-main::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4rpx;
background: #27B25F;
}
.region-info {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16rpx;
}
.region-name {
font-size: 30rpx;
font-weight: 600;
color: #2c3e50;
}
.region-revenue {
font-size: 32rpx;
font-weight: 700;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.region-metrics {
display: flex;
align-items: center;
gap: 24rpx;
}
.metric-item {
text-align: center;
}
.metric-label {
font-size: 22rpx;
color: #6c757d;
margin-bottom: 4rpx;
}
.metric-value {
font-size: 26rpx;
font-weight: 600;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.metric-value.rate {
color: #27B25F;
}
.metric-value.rate.incomplete {
color: #ff9f43;
}
.metric-value.fraction {
color: #6c757d;
}
.metric-value.fraction.incomplete {
color: #ff4757;
}
.expand-indicator {
margin-left: auto;
}
.expand-icon {
font-size: 20rpx;
color: #999;
}
.service-sublist {
background: white;
border-top: 1rpx solid #e9ecef;
padding: 16rpx 0 0;
}
.subservice-card {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16rpx 20rpx;
margin: 8rpx 16rpx;
background: #f8f9fa;
border-radius: 8rpx;
border: 1rpx solid rgba(0, 0, 0, 0.04);
}
.subservice-card.visited .subservice-name {
color: #27B25F;
}
.subservice-info {
flex: 1;
}
.subservice-name {
font-size: 26rpx;
font-weight: 600;
color: #2c3e50;
margin-bottom: 4rpx;
}
.subservice-revenue {
font-size: 24rpx;
font-weight: 600;
color: #27B25F;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
}
.subservice-status {
font-size: 22rpx;
font-weight: 600;
color: #6c757d;
font-family: 'DIN Alternate', 'Bahnschrift', monospace;
margin-right: 16rpx;
}
.subservice-status.incomplete {
color: #ff4757;
}
.subservice-arrow {
font-size: 20rpx;
color: #999;
font-weight: 600;
}
/* 微信小程序兼容性修正 - 移除不支持的特性 */
/* 移除 @media 查询,改用 flex 替代 grid */
</style>