feat(wms): 新增带改判记录的钢卷列表接口及展示
feat(crm): 在订单异议页面添加异议内容和处理结果的HTML展示 feat(erp): 新增ERP仪表盘页面并优化采购订单表单 refactor(wms): 移除钢卷列表中的冗余代码并添加改判原因列
This commit is contained in:
804
klp-ui/src/views/erp/dashboard/index.vue
Normal file
804
klp-ui/src/views/erp/dashboard/index.vue
Normal file
@@ -0,0 +1,804 @@
|
||||
<template>
|
||||
<div class="erp-dashboard-page">
|
||||
<section class="stats-section">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon supplier-icon">
|
||||
<i class="el-icon-office-building"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ supplierCount }}</div>
|
||||
<div class="stat-label">供应商总数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon order-icon">
|
||||
<i class="el-icon-document"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ orderCount }}</div>
|
||||
<div class="stat-label">采购订单总数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon doing-icon">
|
||||
<i class="el-icon-loading"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ doingOrderCount }}</div>
|
||||
<div class="stat-label">执行中订单</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon complete-icon">
|
||||
<i class="el-icon-circle-check"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ completeOrderCount }}</div>
|
||||
<div class="stat-label">已完成订单</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="charts-section">
|
||||
<div class="chart-card">
|
||||
<div class="chart-header">
|
||||
<span>订单状态分布</span>
|
||||
</div>
|
||||
<div ref="statusChart" class="chart-container"></div>
|
||||
</div>
|
||||
<div class="chart-card">
|
||||
<div class="chart-header">
|
||||
<span>供应商订单占比</span>
|
||||
</div>
|
||||
<div ref="supplierChart" class="chart-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="charts-section">
|
||||
<div class="chart-card full-width">
|
||||
<div class="chart-header">
|
||||
<span>订单趋势(按天)</span>
|
||||
</div>
|
||||
<div ref="trendChart" class="chart-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="charts-section">
|
||||
<div class="chart-card">
|
||||
<div class="chart-header">
|
||||
<span>业务员订单分布</span>
|
||||
</div>
|
||||
<div ref="salesmanBarChart" class="chart-container"></div>
|
||||
</div>
|
||||
<div class="chart-card">
|
||||
<div class="chart-header">
|
||||
<span>部门订单分布</span>
|
||||
</div>
|
||||
<div ref="deptBarChart" class="chart-container"></div>
|
||||
</div>
|
||||
<div class="chart-card">
|
||||
<div class="chart-header">
|
||||
<span>按业务员订单占比(饼图)</span>
|
||||
</div>
|
||||
<div ref="salesmanPieChart" class="chart-container"></div>
|
||||
</div>
|
||||
<div class="chart-card">
|
||||
<div class="chart-header">
|
||||
<span>按部门订单占比(饼图)</span>
|
||||
</div>
|
||||
<div ref="deptPieChart" class="chart-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="charts-section">
|
||||
<div class="chart-card">
|
||||
<div class="chart-header">
|
||||
<span>供应商信用等级分布</span>
|
||||
</div>
|
||||
<div ref="creditChart" class="chart-container"></div>
|
||||
</div>
|
||||
<div class="chart-card">
|
||||
<div class="chart-header">
|
||||
<span>供应商类型分布</span>
|
||||
</div>
|
||||
<div ref="typeChart" class="chart-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listSupplier, listPurchaseOrder } from '@/api/erp/purchase'
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
export default {
|
||||
name: 'ErpDashboard',
|
||||
data() {
|
||||
return {
|
||||
supplierCount: 0,
|
||||
orderCount: 0,
|
||||
doingOrderCount: 0,
|
||||
completeOrderCount: 0,
|
||||
supplierList: [],
|
||||
orderList: [],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadData()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.statusChart) this.statusChart.dispose()
|
||||
if (this.supplierChart) this.supplierChart.dispose()
|
||||
if (this.trendChart) this.trendChart.dispose()
|
||||
if (this.creditChart) this.creditChart.dispose()
|
||||
if (this.typeChart) this.typeChart.dispose()
|
||||
if (this.salesmanBarChart) this.salesmanBarChart.dispose()
|
||||
if (this.salesmanPieChart) this.salesmanPieChart.dispose()
|
||||
if (this.deptBarChart) this.deptBarChart.dispose()
|
||||
if (this.deptPieChart) this.deptPieChart.dispose()
|
||||
if (this.supplierBarChart) this.supplierBarChart.dispose()
|
||||
if (this.supplierPieChart) this.supplierPieChart.dispose()
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
},
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.loading = true
|
||||
try {
|
||||
const [supplierRes, orderRes] = await Promise.all([
|
||||
listSupplier({ pageNum: 1, pageSize: 100000 }),
|
||||
listPurchaseOrder({ pageNum: 1, pageSize: 100000 })
|
||||
])
|
||||
this.supplierList = supplierRes.rows || []
|
||||
this.orderList = orderRes.rows || []
|
||||
this.supplierCount = this.supplierList.length
|
||||
this.orderCount = this.orderList.length
|
||||
this.doingOrderCount = this.orderList.filter(o => o.orderStatus === 1).length
|
||||
this.completeOrderCount = this.orderList.filter(o => o.orderStatus === 3).length
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.initCharts()
|
||||
})
|
||||
} catch (error) {
|
||||
this.$message.error('加载数据失败')
|
||||
console.error(error)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
initCharts() {
|
||||
this.initStatusChart()
|
||||
this.initSupplierChart()
|
||||
this.initTrendChart()
|
||||
this.initCreditChart()
|
||||
this.initTypeChart()
|
||||
this.initSalesmanCharts()
|
||||
this.initDeptCharts()
|
||||
this.initSupplierNameCharts()
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
},
|
||||
handleResize() {
|
||||
this.statusChart && this.statusChart.resize()
|
||||
this.supplierChart && this.supplierChart.resize()
|
||||
this.trendChart && this.trendChart.resize()
|
||||
this.creditChart && this.creditChart.resize()
|
||||
this.typeChart && this.typeChart.resize()
|
||||
this.salesmanBarChart && this.salesmanBarChart.resize()
|
||||
this.salesmanPieChart && this.salesmanPieChart.resize()
|
||||
this.deptBarChart && this.deptBarChart.resize()
|
||||
this.deptPieChart && this.deptPieChart.resize()
|
||||
this.supplierBarChart && this.supplierBarChart.resize()
|
||||
this.supplierPieChart && this.supplierPieChart.resize()
|
||||
},
|
||||
initStatusChart() {
|
||||
this.statusChart = echarts.init(this.$refs.statusChart)
|
||||
const statusMap = {
|
||||
0: '草稿',
|
||||
1: '执行中',
|
||||
2: '部分到货',
|
||||
3: '已完成',
|
||||
4: '已取消'
|
||||
}
|
||||
const statusData = {}
|
||||
this.orderList.forEach(order => {
|
||||
const status = order.orderStatus || 0
|
||||
statusData[status] = (statusData[status] || 0) + 1
|
||||
})
|
||||
const data = Object.keys(statusData).map(key => ({
|
||||
name: statusMap[key],
|
||||
value: statusData[key]
|
||||
}))
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '订单状态',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}: {c}'
|
||||
},
|
||||
data: data
|
||||
}
|
||||
]
|
||||
}
|
||||
this.statusChart.setOption(option)
|
||||
},
|
||||
initSupplierChart() {
|
||||
this.supplierChart = echarts.init(this.$refs.supplierChart)
|
||||
const supplierOrderCount = {}
|
||||
this.orderList.forEach(order => {
|
||||
const supplierName = order.supplierName || '未知'
|
||||
supplierOrderCount[supplierName] = (supplierOrderCount[supplierName] || 0) + 1
|
||||
})
|
||||
let data = Object.keys(supplierOrderCount).map(name => ({
|
||||
name,
|
||||
value: supplierOrderCount[name]
|
||||
}))
|
||||
data = data.sort((a, b) => b.value - a.value).slice(0, 10)
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '供应商订单',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}: {c}'
|
||||
},
|
||||
data: data
|
||||
}
|
||||
]
|
||||
}
|
||||
this.supplierChart.setOption(option)
|
||||
},
|
||||
initTrendChart() {
|
||||
this.trendChart = echarts.init(this.$refs.trendChart)
|
||||
const dayData = {}
|
||||
this.orderList.forEach(order => {
|
||||
if (order.orderDate) {
|
||||
const day = order.orderDate
|
||||
dayData[day] = (dayData[day] || 0) + 1
|
||||
}
|
||||
})
|
||||
const days = Object.keys(dayData).sort()
|
||||
const counts = days.map(d => dayData[d])
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
legend: {
|
||||
data: ['订单数量']
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: days,
|
||||
axisLabel: {
|
||||
rotate: 45
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'inside',
|
||||
start: 0,
|
||||
end: 100
|
||||
},
|
||||
{
|
||||
start: 0,
|
||||
end: 100
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '订单数量',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: counts,
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(80, 141, 255, 0.5)' },
|
||||
{ offset: 1, color: 'rgba(80, 141, 255, 0.1)' }
|
||||
])
|
||||
},
|
||||
lineStyle: {
|
||||
color: '#508dff'
|
||||
},
|
||||
itemStyle: {
|
||||
color: '#508dff'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.trendChart.setOption(option)
|
||||
},
|
||||
initCreditChart() {
|
||||
this.creditChart = echarts.init(this.$refs.creditChart)
|
||||
const creditData = {}
|
||||
this.supplierList.forEach(supplier => {
|
||||
const credit = supplier.creditRating || '-'
|
||||
creditData[credit] = (creditData[credit] || 0) + 1
|
||||
})
|
||||
const data = Object.keys(creditData).map(key => ({
|
||||
name: key,
|
||||
value: creditData[key]
|
||||
}))
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Object.keys(creditData)
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '供应商数量',
|
||||
type: 'bar',
|
||||
data: Object.values(creditData),
|
||||
itemStyle: {
|
||||
color: function (params) {
|
||||
const colorMap = {
|
||||
'A': '#67c23a',
|
||||
'B': '#e6a23c',
|
||||
'C': '#f56c6c',
|
||||
'D': '#909399',
|
||||
'-': '#409eff'
|
||||
}
|
||||
return colorMap[params.name] || '#409eff'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.creditChart.setOption(option)
|
||||
},
|
||||
initTypeChart() {
|
||||
this.typeChart = echarts.init(this.$refs.typeChart)
|
||||
const typeData = {}
|
||||
this.supplierList.forEach(supplier => {
|
||||
const type = supplier.type === 'RAW' ? '原料供应商' : '其他供应商'
|
||||
typeData[type] = (typeData[type] || 0) + 1
|
||||
})
|
||||
const data = Object.keys(typeData).map(key => ({
|
||||
name: key,
|
||||
value: typeData[key]
|
||||
}))
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '供应商类型',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}: {c}'
|
||||
},
|
||||
data: data
|
||||
}
|
||||
]
|
||||
}
|
||||
this.typeChart.setOption(option)
|
||||
},
|
||||
initSalesmanCharts() {
|
||||
// 柱状图
|
||||
this.salesmanBarChart = echarts.init(this.$refs.salesmanBarChart)
|
||||
const salesmanData = {}
|
||||
this.orderList.forEach(order => {
|
||||
const salesman = order.salesman || '未知'
|
||||
salesmanData[salesman] = (salesmanData[salesman] || 0) + 1
|
||||
})
|
||||
const salesmanList = Object.keys(salesmanData).sort((a, b) => salesmanData[b] - salesmanData[a])
|
||||
const salesmanCounts = salesmanList.map(s => salesmanData[s])
|
||||
|
||||
const barOption = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: salesmanList,
|
||||
axisLabel: {
|
||||
rotate: 45
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '订单数量',
|
||||
type: 'bar',
|
||||
data: salesmanCounts,
|
||||
itemStyle: {
|
||||
color: '#67c23a'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.salesmanBarChart.setOption(barOption)
|
||||
|
||||
// 饼图
|
||||
this.salesmanPieChart = echarts.init(this.$refs.salesmanPieChart)
|
||||
let pieData = salesmanList.map(name => ({
|
||||
name,
|
||||
value: salesmanData[name]
|
||||
}))
|
||||
pieData = pieData.slice(0, 10)
|
||||
|
||||
const pieOption = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '业务员订单',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}: {c}'
|
||||
},
|
||||
data: pieData
|
||||
}
|
||||
]
|
||||
}
|
||||
this.salesmanPieChart.setOption(pieOption)
|
||||
},
|
||||
initDeptCharts() {
|
||||
// 柱状图
|
||||
this.deptBarChart = echarts.init(this.$refs.deptBarChart)
|
||||
const deptData = {}
|
||||
this.orderList.forEach(order => {
|
||||
const dept = order.deptName || '未知'
|
||||
deptData[dept] = (deptData[dept] || 0) + 1
|
||||
})
|
||||
const deptList = Object.keys(deptData).sort((a, b) => deptData[b] - deptData[a])
|
||||
const deptCounts = deptList.map(d => deptData[d])
|
||||
|
||||
const barOption = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: deptList,
|
||||
axisLabel: {
|
||||
rotate: 45
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '订单数量',
|
||||
type: 'bar',
|
||||
data: deptCounts,
|
||||
itemStyle: {
|
||||
color: '#e6a23c'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.deptBarChart.setOption(barOption)
|
||||
|
||||
// 饼图
|
||||
this.deptPieChart = echarts.init(this.$refs.deptPieChart)
|
||||
let pieData = deptList.map(name => ({
|
||||
name,
|
||||
value: deptData[name]
|
||||
}))
|
||||
pieData = pieData.slice(0, 10)
|
||||
|
||||
const pieOption = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '部门订单',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}: {c}'
|
||||
},
|
||||
data: pieData
|
||||
}
|
||||
]
|
||||
}
|
||||
this.deptPieChart.setOption(pieOption)
|
||||
},
|
||||
initSupplierNameCharts() {
|
||||
// 柱状图
|
||||
this.supplierBarChart = echarts.init(this.$refs.supplierBarChart)
|
||||
const supplierData = {}
|
||||
this.orderList.forEach(order => {
|
||||
const supplier = order.supplierName || '未知'
|
||||
supplierData[supplier] = (supplierData[supplier] || 0) + 1
|
||||
})
|
||||
const supplierList = Object.keys(supplierData).sort((a, b) => supplierData[b] - supplierData[a])
|
||||
const supplierCounts = supplierList.map(s => supplierData[s])
|
||||
|
||||
const barOption = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: supplierList.slice(0, 15),
|
||||
axisLabel: {
|
||||
rotate: 45
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '订单数量',
|
||||
type: 'bar',
|
||||
data: supplierCounts.slice(0, 15),
|
||||
itemStyle: {
|
||||
color: '#f56c6c'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.supplierBarChart.setOption(barOption)
|
||||
|
||||
// 饼图
|
||||
this.supplierPieChart = echarts.init(this.$refs.supplierPieChart)
|
||||
let pieData = supplierList.map(name => ({
|
||||
name,
|
||||
value: supplierData[name]
|
||||
}))
|
||||
pieData = pieData.slice(0, 10)
|
||||
|
||||
const pieOption = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '供应商订单',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}: {c}'
|
||||
},
|
||||
data: pieData
|
||||
}
|
||||
]
|
||||
}
|
||||
this.supplierPieChart.setOption(pieOption)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.erp-dashboard-page {
|
||||
padding: 16px;
|
||||
min-height: 100%;
|
||||
background: #f0f2f5;
|
||||
}
|
||||
|
||||
.stats-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28px;
|
||||
|
||||
&.supplier-icon {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.order-icon {
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.doing-icon {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.complete-icon {
|
||||
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #1f2a37;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #7a8694;
|
||||
}
|
||||
|
||||
.charts-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.chart-card {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||
|
||||
&.full-width {
|
||||
grid-column: span 2;
|
||||
}
|
||||
}
|
||||
|
||||
.chart-header {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1f2a37;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user