订单统计
This commit is contained in:
parent
4615ee99f3
commit
1afa287f5d
@ -175,4 +175,13 @@ export const orderExportGet = (params) => {
|
|||||||
*/
|
*/
|
||||||
export const orderSetstatusPatch = (data) => {
|
export const orderSetstatusPatch = (data) => {
|
||||||
return http.patch('/order/setstatus', data);
|
return http.patch('/order/setstatus', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取订单统计数据
|
||||||
|
* @param {Object} params - 查询参数
|
||||||
|
* @returns {Promise<{totalOriginalAmount: number, totalDiscountAmount: number, totalActualAmount: number, totalRefundAmount: number}>}
|
||||||
|
*/
|
||||||
|
export const orderStatsGet = (params) => {
|
||||||
|
return http.get('/order/stats', { params });
|
||||||
};
|
};
|
||||||
@ -1,7 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="system-menu-container layout-padding">
|
<div class="system-menu-container layout-padding">
|
||||||
|
<!-- 统计区块 -->
|
||||||
|
<div class="registration-stats-container">
|
||||||
|
<div class="stats-card" v-loading="statsLoading">
|
||||||
|
<div class="stats-row">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">原金额</div>
|
||||||
|
<div class="stat-value">{{ animatedCounts.totalOriginalAmount }}<span class="stat-unit">元</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-divider"></div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">优惠金额</div>
|
||||||
|
<div class="stat-value">{{ animatedCounts.totalDiscountAmount }}<span class="stat-unit">元</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-divider"></div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">实付金额</div>
|
||||||
|
<div class="stat-value">{{ animatedCounts.totalActualAmount }}<span class="stat-unit">元</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-divider"></div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-label">退款金额</div>
|
||||||
|
<div class="stat-value" style="color: #e6a23c;">{{ animatedCounts.totalRefundAmount }}<span class="stat-unit">元</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<ProTable ref="tableRef" :request-api="orderPageGet" :columns="columns" :pagination="true"
|
<ProTable ref="tableRef" :request-api="orderPageGet" :columns="columns" :pagination="true"
|
||||||
:tool-button="true">
|
:tool-button="true" @search="fetchStats" @reset="fetchStats">
|
||||||
<template #tools>
|
<template #tools>
|
||||||
<el-button v-auth="'order:export'" type="primary" :loading="exportLoading" @click="handleExport">
|
<el-button v-auth="'order:export'" type="primary" :loading="exportLoading" @click="handleExport">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
@ -49,7 +75,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #action="scope">
|
<template #action="scope">
|
||||||
<el-button size="small" text type="primary" @click="onOpenMenu(scope.row.id)">
|
<el-button size="small" text type="primary" @click="onOpenMenu(scope.row.id)">
|
||||||
查看详情 </el-button>
|
查看详情
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</ProTable>
|
</ProTable>
|
||||||
|
|
||||||
@ -77,18 +104,76 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup >
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { Download } from '@element-plus/icons-vue';
|
import { Download } from '@element-plus/icons-vue';
|
||||||
import ProTable from '/@/components/ProTable/index.vue';
|
import ProTable from '/@/components/ProTable/index.vue';
|
||||||
import { orderPageGet , orderDetailGet, orderExportGet } from '/@/api/match/order';
|
import { orderPageGet, orderDetailGet, orderExportGet, orderStatsGet } from '/@/api/match/order';
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const exportLoading = ref(false);
|
const exportLoading = ref(false);
|
||||||
|
const statsLoading = ref(false);
|
||||||
|
|
||||||
|
// 统计数据
|
||||||
|
const statsData = ref({
|
||||||
|
totalOriginalAmount: 0,
|
||||||
|
totalDiscountAmount: 0,
|
||||||
|
totalActualAmount: 0,
|
||||||
|
totalRefundAmount: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
// 动画计数
|
||||||
|
const animatedCounts = ref({
|
||||||
|
totalOriginalAmount: '0.00',
|
||||||
|
totalDiscountAmount: '0.00',
|
||||||
|
totalActualAmount: '0.00',
|
||||||
|
totalRefundAmount: '0.00'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 数字动画效果
|
||||||
|
const animateNumber = (key, targetValue) => {
|
||||||
|
const duration = 1000;
|
||||||
|
const startTime = Date.now();
|
||||||
|
const startValue = parseFloat(animatedCounts.value[key]) || 0;
|
||||||
|
|
||||||
|
const animate = () => {
|
||||||
|
const elapsed = Date.now() - startTime;
|
||||||
|
const progress = Math.min(elapsed / duration, 1);
|
||||||
|
const easeProgress = 1 - Math.pow(1 - progress, 3);
|
||||||
|
const currentValue = startValue + (targetValue - startValue) * easeProgress;
|
||||||
|
animatedCounts.value[key] = currentValue.toFixed(2);
|
||||||
|
|
||||||
|
if (progress < 1) {
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
animate();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取统计数据
|
||||||
|
const fetchStats = async () => {
|
||||||
|
try {
|
||||||
|
statsLoading.value = true;
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
const searchParams = tableRef.value?.searchParam || {};
|
||||||
|
const { succeeded, data } = await orderStatsGet(searchParams);
|
||||||
|
if (succeeded && data) {
|
||||||
|
statsData.value = data;
|
||||||
|
animateNumber('totalOriginalAmount', data.totalOriginalAmount);
|
||||||
|
animateNumber('totalDiscountAmount', data.totalDiscountAmount);
|
||||||
|
animateNumber('totalActualAmount', data.totalActualAmount);
|
||||||
|
animateNumber('totalRefundAmount', data.totalRefundAmount);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取统计数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
statsLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
orderNo: '',
|
orderNo: '',
|
||||||
eventId: 0,
|
eventId: 0,
|
||||||
eventName: '',
|
eventName: '',
|
||||||
registrationMode: 0,
|
registrationMode: 0,
|
||||||
@ -101,187 +186,226 @@ const formData = ref({
|
|||||||
status: 0,
|
status: 0,
|
||||||
createdTime: '',
|
createdTime: '',
|
||||||
paidTime: '',
|
paidTime: '',
|
||||||
items:[],
|
items: [],
|
||||||
persons:[]
|
persons: []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{ prop: 'orderNo', label: '订单编号', align: 'center', search: { el: 'input', }, fixed: 'left', width: 150 },
|
{ prop: 'orderNo', label: '订单编号', align: 'center', search: { el: 'input', }, fixed: 'left', width: 150 },
|
||||||
{ width: 180, prop: 'unitName', label: '单位名称', align: 'center', },
|
{ width: 180, prop: 'unitName', label: '单位名称', align: 'center', },
|
||||||
{ width: 120, prop: 'eventName', label: '所属赛事', search: { el: 'input', }, },
|
{ width: 120, prop: 'eventName', label: '所属赛事', search: { el: 'input', }, },
|
||||||
{ width: 120, prop: 'orderType', label: '订单类型', search: { el: 'select', }, enum: [{ label: '全部', value: 0 }, { label: '收款', value: 1 }, { label: '退款', value: 2 },], },
|
{ width: 120, prop: 'orderType', label: '订单类型', search: { el: 'select', }, enum: [{ label: '全部', value: 0 }, { label: '收款', value: 1 }, { label: '退款', value: 2 },], },
|
||||||
{ width: 120, prop: 'relatedOrderNo', label: '关联订单' },
|
{ width: 120, prop: 'relatedOrderNo', label: '关联订单' },
|
||||||
{ width: 100, prop: 'paymentMethod', label: '支付方式', search: { el: 'select', }, enum: [{ label: '全部', value: 0 }, { label: '线上', value: 2 }, { label: '线下', value: 1 },], },
|
{ width: 100, prop: 'paymentMethod', label: '支付方式', search: { el: 'select', }, enum: [{ label: '全部', value: 0 }, { label: '线上', value: 2 }, { label: '线下', value: 1 },], },
|
||||||
{ width: 100, prop: 'paymentProofUrl', label: '付款凭证' },
|
{ width: 100, prop: 'paymentProofUrl', label: '付款凭证' },
|
||||||
{ width: 100, prop: 'registrationMode', label: '报名方式', search: { el: 'select', }, enum: [{ label: '全部', value: 0 }, { label: '个人', value: 1 }, { label: '团队', value: 2 },], },
|
{ width: 100, prop: 'registrationMode', label: '报名方式', search: { el: 'select', }, enum: [{ label: '全部', value: 0 }, { label: '个人', value: 1 }, { label: '团队', value: 2 },], },
|
||||||
{ width: 120, prop: 'contactName', label: '报名用户' },
|
{ width: 120, prop: 'contactName', label: '报名用户' },
|
||||||
{ width: 120, prop: 'contactPhone', label: '报名账号', search: { el: 'input' } },
|
{ width: 120, prop: 'contactPhone', label: '报名账号', search: { el: 'input' } },
|
||||||
{ width: 100, prop: 'originalAmount', label: '原金额' },
|
{ width: 100, prop: 'originalAmount', label: '原金额' },
|
||||||
{ width: 120, prop: 'actualAmount', label: '实付金额' },
|
{ width: 120, prop: 'actualAmount', label: '实付金额' },
|
||||||
{ width: 100, prop: 'discountAmount', label: '优惠金额' },
|
{ width: 100, prop: 'discountAmount', label: '优惠金额' },
|
||||||
{ width: 100, prop: 'refundAmount', label: '退款金额', align: 'center' },
|
{ width: 100, prop: 'refundAmount', label: '退款金额', align: 'center' },
|
||||||
{ width: 90, prop: 'orderStatus', label: '订单状态', search: { el: 'select', }, enum: [{ label: '全部', value: '' }, { label: '待支付', value: 0 }, { label: '已支付', value: 1 }, { label: '已退款', value: 3 }, { label: '报名失败', value: 6 },], },
|
{ width: 90, prop: 'orderStatus', label: '订单状态', search: { el: 'select', }, enum: [{ label: '全部', value: '' }, { label: '待支付', value: 0 }, { label: '已支付', value: 1 }, { label: '已退款', value: 3 }, { label: '报名失败', value: 6 },], },
|
||||||
{ width: 160, prop: 'createdTime', label: '生成时间', search: { el: 'date-picker', props: { type: 'daterange' } } },
|
{ width: 160, prop: 'createdTime', label: '生成时间', search: { el: 'date-picker', props: { type: 'daterange' } } },
|
||||||
{ prop: 'action', label: '操作', align: 'center', fixed: 'right', width: 120, },
|
{ prop: 'action', label: '操作', align: 'center', fixed: 'right', width: 120, },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const isShowDialog = ref(false);
|
const isShowDialog = ref(false);
|
||||||
const detailLoading = ref(false);
|
const detailLoading = ref(false);
|
||||||
|
|
||||||
const formatAmount = (value) => {
|
const formatAmount = (value) => {
|
||||||
if (value === null || value === undefined || value === '') return '-';
|
if (value === null || value === undefined || value === '') return '-';
|
||||||
const num = Number(value);
|
const num = Number(value);
|
||||||
if (isNaN(num) || num === 0) return '-';
|
if (isNaN(num) || num === 0) return '-';
|
||||||
return num.toFixed(2);
|
return num.toFixed(2);
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatActualAmount = (row) => {
|
const formatActualAmount = (row) => {
|
||||||
if (row.isRefundOrder) {
|
if (row.isRefundOrder) {
|
||||||
if (row.relatedOrderActualAmount !== null && row.relatedOrderActualAmount !== undefined) {
|
if (row.relatedOrderActualAmount !== null && row.relatedOrderActualAmount !== undefined) {
|
||||||
const num = Number(row.relatedOrderActualAmount);
|
const num = Number(row.relatedOrderActualAmount);
|
||||||
const amountStr = isNaN(num) || num === 0 ? '-' : num.toFixed(2);
|
const amountStr = isNaN(num) || num === 0 ? '-' : num.toFixed(2);
|
||||||
return amountStr;
|
return amountStr;
|
||||||
}
|
}
|
||||||
return '-';
|
return '-';
|
||||||
} else {
|
} else {
|
||||||
return formatAmount(row.actualAmount);
|
return formatAmount(row.actualAmount);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const normalizeNames = (value) => {
|
|
||||||
if (Array.isArray(value)) return value.filter(Boolean).join('、');
|
|
||||||
if (typeof value === 'string') return value;
|
|
||||||
return '';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ChargeMode 枚举值:0=免费,1=定价(赛事),2=单价(赛事),3=单价(项目)
|
// ChargeMode 枚举值:0=免费,1=定价(赛事),2=单价(赛事),3=单价(项目)
|
||||||
// 只有单价(项目)时才显示费用列
|
// 只有单价(项目)时才显示费用列
|
||||||
const shouldShowFee = computed(() => {
|
const shouldShowFee = computed(() => {
|
||||||
return formData.value?.chargeMode === 3;
|
return formData.value?.chargeMode === 3;
|
||||||
});
|
});
|
||||||
|
|
||||||
const detailTableData = computed(() => {
|
const detailTableData = computed(() => {
|
||||||
const items = formData.value?.items ?? [];
|
const items = formData.value?.items ?? [];
|
||||||
const persons = formData.value?.persons ?? [];
|
const persons = formData.value?.persons ?? [];
|
||||||
|
|
||||||
return items.map((item) => {
|
return items.map((item) => {
|
||||||
// 方案1: 使用 registrationItemId 进行精确匹配(强一致)
|
let personNamesByItem = persons
|
||||||
let personNamesByItem = persons
|
.filter((p) => String(p?.registrationItemId) === String(item?.id))
|
||||||
.filter((p) => String(p?.registrationItemId) === String(item?.id))
|
.map((p) => p?.name)
|
||||||
.map((p) => p?.name)
|
.filter(Boolean);
|
||||||
.filter(Boolean);
|
|
||||||
|
if (personNamesByItem.length === 0) {
|
||||||
// 方案2: 使用项目ID匹配
|
personNamesByItem = persons
|
||||||
if (personNamesByItem.length === 0) {
|
.filter((p) => String(p?.projectId) === String(item?.projectId))
|
||||||
personNamesByItem = persons
|
.map((p) => p?.name)
|
||||||
.filter((p) => String(p?.projectId) === String(item?.projectId))
|
.filter(Boolean);
|
||||||
.map((p) => p?.name)
|
}
|
||||||
.filter(Boolean);
|
|
||||||
}
|
if (personNamesByItem.length === 0) {
|
||||||
|
personNamesByItem = [...new Set(
|
||||||
// 方案3: 最后保底,用项目名和组名去重匹配
|
persons
|
||||||
if (personNamesByItem.length === 0) {
|
.filter((p) => p?.groupName === item?.groupName)
|
||||||
personNamesByItem = [...new Set(
|
.map((p) => p?.name)
|
||||||
persons
|
.filter(Boolean)
|
||||||
.filter((p) => p?.groupName === item?.groupName)
|
)];
|
||||||
.map((p) => p?.name)
|
}
|
||||||
.filter(Boolean)
|
|
||||||
)];
|
const participantNames = personNamesByItem.length > 0
|
||||||
}
|
? personNamesByItem.join('、')
|
||||||
|
: '-';
|
||||||
const participantNames = personNamesByItem.length > 0
|
const fee = item?.fee ?? item?.subtotal ?? ((Number(item?.unitPrice) || 0) * (Number(item?.personCount) || 0));
|
||||||
? personNamesByItem.join('、')
|
return {
|
||||||
: '-';
|
projectName: item?.projectName ?? '-',
|
||||||
const fee = item?.fee ?? item?.subtotal ?? ((Number(item?.unitPrice) || 0) * (Number(item?.personCount) || 0));
|
groupName: item?.groupName ?? item?.projectTypeName ?? '-',
|
||||||
return {
|
participantNames,
|
||||||
projectName: item?.projectName ?? '-',
|
fee,
|
||||||
groupName: item?.groupName ?? item?.projectTypeName ?? '-',
|
};
|
||||||
participantNames,
|
});
|
||||||
fee,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const onOpenMenu = async(id) => {
|
const onOpenMenu = async (id) => {
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
isShowDialog.value = true;
|
isShowDialog.value = true;
|
||||||
detailLoading.value = true;
|
detailLoading.value = true;
|
||||||
const { succeeded, data } = await orderDetailGet({ id });
|
const { succeeded, data } = await orderDetailGet({ id });
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
ElMessage.error('订单详情加载失败');
|
ElMessage.error('订单详情加载失败');
|
||||||
formData.value.items = [];
|
formData.value.items = [];
|
||||||
formData.value.persons = [];
|
formData.value.persons = [];
|
||||||
detailLoading.value = false;
|
detailLoading.value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
formData.value = {
|
formData.value = {
|
||||||
...formData.value,
|
...formData.value,
|
||||||
...(data ?? {}),
|
...(data ?? {}),
|
||||||
items: data?.items ?? [],
|
items: data?.items ?? [],
|
||||||
persons: data?.persons ?? [],
|
persons: data?.persons ?? [],
|
||||||
};
|
};
|
||||||
detailLoading.value = false;
|
detailLoading.value = false;
|
||||||
isShowDialog.value = true;
|
isShowDialog.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExport = async () => {
|
const handleExport = async () => {
|
||||||
try {
|
try {
|
||||||
exportLoading.value = true;
|
exportLoading.value = true;
|
||||||
|
|
||||||
const searchParams = tableRef.value?.searchParam || {};
|
const searchParams = tableRef.value?.searchParam || {};
|
||||||
|
|
||||||
const response = await orderExportGet(searchParams);
|
const response = await orderExportGet(searchParams);
|
||||||
|
|
||||||
const blob = new Blob([response], {
|
const blob = new Blob([response], {
|
||||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
});
|
});
|
||||||
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
const url = window.URL.createObjectURL(blob);
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
link.href = url;
|
link.href = url;
|
||||||
link.download = `订单列表_${new Date().getTime()}.xlsx`;
|
link.download = `订单列表_${new Date().getTime()}.xlsx`;
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
window.URL.revokeObjectURL(url);
|
window.URL.revokeObjectURL(url);
|
||||||
|
|
||||||
ElMessage.success('导出成功');
|
ElMessage.success('导出成功');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('导出失败:', error);
|
console.error('导出失败:', error);
|
||||||
ElMessage.error('导出失败,请稍后重试');
|
ElMessage.error('导出失败,请稍后重试');
|
||||||
} finally {
|
} finally {
|
||||||
exportLoading.value = false;
|
exportLoading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchStats();
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.registration-stats-container {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 24px 32px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-unit {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 60px;
|
||||||
|
background-color: #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
.dialog-footer {
|
.dialog-footer {
|
||||||
margin-top: 80px;
|
margin-top: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 时长组合框样式 */
|
/* 响应式设计 - 移动端垂直排列 */
|
||||||
.duration-row {
|
@media (max-width: 768px) {
|
||||||
display: flex;
|
.stats-card {
|
||||||
align-items: center;
|
padding: 16px;
|
||||||
gap: 8px;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.duration-row .el-input {
|
.stats-row {
|
||||||
width: 120px;
|
flex-direction: column;
|
||||||
}
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.duration-separator {
|
.stat-divider {
|
||||||
color: #606266;
|
width: 60%;
|
||||||
font-size: 14px;
|
height: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.duration-label {
|
.stat-value {
|
||||||
color: #909399;
|
font-size: 24px;
|
||||||
font-size: 14px;
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user