|
@@ -1,40 +1,48 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div class="department-efficiency-view">
|
|
<div class="department-efficiency-view">
|
|
|
- <!-- 1. 页面头部 -->
|
|
|
|
|
<header class="page-header">
|
|
<header class="page-header">
|
|
|
<h1 class="page-title">综合运营分析</h1>
|
|
<h1 class="page-title">综合运营分析</h1>
|
|
|
<p class="page-description">分析各部门的平均销售额与渠道商品多样性。</p>
|
|
<p class="page-description">分析各部门的平均销售额与渠道商品多样性。</p>
|
|
|
</header>
|
|
</header>
|
|
|
|
|
|
|
|
- <!-- 2. 部门运营效率分析 -->
|
|
|
|
|
<section class="chart-area">
|
|
<section class="chart-area">
|
|
|
<div v-if="barChart.loading" class="status-overlay">
|
|
<div v-if="barChart.loading" class="status-overlay">
|
|
|
- <p>hina正在努力加载部门效率数据中...</p>
|
|
|
|
|
|
|
+ <p>正在加载部门效率数据...</p>
|
|
|
</div>
|
|
</div>
|
|
|
- <div v-else-if="barChart.error" class="status-overlay error">
|
|
|
|
|
- <p>部门效率数据加载失败</p>
|
|
|
|
|
- <p class="error-message">{{ barChart.error }}</p>
|
|
|
|
|
|
|
+ <div v-else-if="barChart.message" :class="['status-overlay', { error: barChart.isError }]">
|
|
|
|
|
+ <p>{{ barChart.title }}</p>
|
|
|
|
|
+ <p class="error-message">{{ barChart.message }}</p>
|
|
|
</div>
|
|
</div>
|
|
|
- <div ref="barChartRef" style="width: 100%; height: 500px;"></div>
|
|
|
|
|
|
|
+ <div ref="barChartRef" class="chart-canvas"></div>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
|
|
|
- <!-- 3. 渠道商品多样性分析 -->
|
|
|
|
|
<section class="chart-area">
|
|
<section class="chart-area">
|
|
|
<div v-if="pieChart.loading" class="status-overlay">
|
|
<div v-if="pieChart.loading" class="status-overlay">
|
|
|
- <p>hina正在努力加载渠道多样性数据中...</p>
|
|
|
|
|
|
|
+ <p>正在加载渠道多样性数据...</p>
|
|
|
</div>
|
|
</div>
|
|
|
- <div v-else-if="pieChart.error" class="status-overlay error">
|
|
|
|
|
- <p>渠道多样性数据加载失败</p>
|
|
|
|
|
- <p class="error-message">{{ pieChart.error }}</p>
|
|
|
|
|
|
|
+ <div v-else-if="pieChart.message" :class="['status-overlay', { error: pieChart.isError }]">
|
|
|
|
|
+ <p>{{ pieChart.title }}</p>
|
|
|
|
|
+ <p class="error-message">{{ pieChart.message }}</p>
|
|
|
</div>
|
|
</div>
|
|
|
- <div ref="pieChartRef" style="width: 100%; height: 500px;"></div>
|
|
|
|
|
|
|
+ <div ref="pieChartRef" class="chart-canvas"></div>
|
|
|
</section>
|
|
</section>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import * as echarts from 'echarts';
|
|
|
|
|
-import { getShopChannelDiversity, getShopDepartmentEfficiency } from '@/api/order';
|
|
|
|
|
|
|
+import * as echarts from 'echarts'
|
|
|
|
|
+import { getShopChannelDiversity, getShopDepartmentEfficiency } from '@/api/order'
|
|
|
|
|
+
|
|
|
|
|
+const EMPTY_DATA_HINTS = ['未上传', '请先上传', '暂无数据', '无数据', 'not found', 'no data']
|
|
|
|
|
+
|
|
|
|
|
+function createChartState(defaultTitle) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ loading: true,
|
|
|
|
|
+ title: defaultTitle,
|
|
|
|
|
+ message: '',
|
|
|
|
|
+ isError: false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
name: 'OrderEfficiency',
|
|
name: 'OrderEfficiency',
|
|
@@ -42,111 +50,204 @@ export default {
|
|
|
return {
|
|
return {
|
|
|
barChartInstance: null,
|
|
barChartInstance: null,
|
|
|
pieChartInstance: null,
|
|
pieChartInstance: null,
|
|
|
- barChart: { loading: true, error: null },
|
|
|
|
|
- pieChart: { loading: true, error: null }
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ barChart: createChartState('部门效率数据暂不可用'),
|
|
|
|
|
+ pieChart: createChartState('渠道多样性数据暂不可用')
|
|
|
|
|
+ }
|
|
|
},
|
|
},
|
|
|
mounted() {
|
|
mounted() {
|
|
|
- this.initBarChart();
|
|
|
|
|
- this.initPieChart();
|
|
|
|
|
- window.addEventListener('resize', this.handleResize);
|
|
|
|
|
|
|
+ this.loadCharts()
|
|
|
|
|
+ window.addEventListener('resize', this.handleResize)
|
|
|
},
|
|
},
|
|
|
beforeDestroy() {
|
|
beforeDestroy() {
|
|
|
- window.removeEventListener('resize', this.handleResize);
|
|
|
|
|
- if (this.barChartInstance) this.barChartInstance.dispose();
|
|
|
|
|
- if (this.pieChartInstance) this.pieChartInstance.dispose();
|
|
|
|
|
|
|
+ window.removeEventListener('resize', this.handleResize)
|
|
|
|
|
+ this.disposeCharts()
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
|
|
+ async loadCharts() {
|
|
|
|
|
+ await Promise.all([this.initBarChart(), this.initPieChart()])
|
|
|
|
|
+ },
|
|
|
|
|
+ disposeCharts() {
|
|
|
|
|
+ if (this.barChartInstance) {
|
|
|
|
|
+ this.barChartInstance.dispose()
|
|
|
|
|
+ this.barChartInstance = null
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.pieChartInstance) {
|
|
|
|
|
+ this.pieChartInstance.dispose()
|
|
|
|
|
+ this.pieChartInstance = null
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ resetChartState(target, title) {
|
|
|
|
|
+ target.loading = true
|
|
|
|
|
+ target.title = title
|
|
|
|
|
+ target.message = ''
|
|
|
|
|
+ target.isError = false
|
|
|
|
|
+ },
|
|
|
|
|
+ getErrorMessage(error, fallback) {
|
|
|
|
|
+ return (
|
|
|
|
|
+ error?.response?.data?.message ||
|
|
|
|
|
+ error?.response?.data?.msg ||
|
|
|
|
|
+ error?.message ||
|
|
|
|
|
+ fallback
|
|
|
|
|
+ )
|
|
|
|
|
+ },
|
|
|
|
|
+ isEmptyDataMessage(message) {
|
|
|
|
|
+ const normalized = String(message || '').toLowerCase()
|
|
|
|
|
+ return EMPTY_DATA_HINTS.some(item => normalized.includes(item.toLowerCase()))
|
|
|
|
|
+ },
|
|
|
|
|
+ setChartStatus(target, title, message, isError = false) {
|
|
|
|
|
+ target.title = title
|
|
|
|
|
+ target.message = message
|
|
|
|
|
+ target.isError = isError
|
|
|
|
|
+ },
|
|
|
|
|
+ normalizeBarData(response) {
|
|
|
|
|
+ if (!response || response.success !== true || !response.data) {
|
|
|
|
|
+ throw new Error((response && response.message) || '部门效率数据加载失败')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const rows = Object.entries(response.data)
|
|
|
|
|
+ .map(([name, value]) => ({
|
|
|
|
|
+ name,
|
|
|
|
|
+ value: Number(value)
|
|
|
|
|
+ }))
|
|
|
|
|
+ .filter(item => Number.isFinite(item.value))
|
|
|
|
|
+
|
|
|
|
|
+ if (!rows.length) {
|
|
|
|
|
+ throw new Error('请先上传店铺价值 CSV 文件')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return rows
|
|
|
|
|
+ },
|
|
|
|
|
+ normalizePieData(response) {
|
|
|
|
|
+ if (!response || response.success !== true || !response.data) {
|
|
|
|
|
+ throw new Error((response && response.message) || '渠道多样性数据加载失败')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const rows = Object.entries(response.data)
|
|
|
|
|
+ .map(([name, value]) => ({
|
|
|
|
|
+ name,
|
|
|
|
|
+ value: Number(value)
|
|
|
|
|
+ }))
|
|
|
|
|
+ .filter(item => Number.isFinite(item.value) && item.value > 0)
|
|
|
|
|
+
|
|
|
|
|
+ if (!rows.length) {
|
|
|
|
|
+ throw new Error('请先上传店铺价值 CSV 文件')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return rows
|
|
|
|
|
+ },
|
|
|
|
|
+ initBarChartInstance() {
|
|
|
|
|
+ const chartEl = this.$refs.barChartRef
|
|
|
|
|
+ if (!chartEl) return null
|
|
|
|
|
+ this.barChartInstance = echarts.getInstanceByDom(chartEl) || echarts.init(chartEl)
|
|
|
|
|
+ return this.barChartInstance
|
|
|
|
|
+ },
|
|
|
|
|
+ initPieChartInstance() {
|
|
|
|
|
+ const chartEl = this.$refs.pieChartRef
|
|
|
|
|
+ if (!chartEl) return null
|
|
|
|
|
+ this.pieChartInstance = echarts.getInstanceByDom(chartEl) || echarts.init(chartEl)
|
|
|
|
|
+ return this.pieChartInstance
|
|
|
|
|
+ },
|
|
|
async initBarChart() {
|
|
async initBarChart() {
|
|
|
- this.barChart.loading = true;
|
|
|
|
|
|
|
+ this.resetChartState(this.barChart, '部门效率数据暂不可用')
|
|
|
try {
|
|
try {
|
|
|
- const response = await axios.get('/api/shop/import/department-efficiency');
|
|
|
|
|
- if (!response.data || !response.data.success) {
|
|
|
|
|
- throw new Error(response.data.message || 'REPLACED__');
|
|
|
|
|
- }
|
|
|
|
|
- const rawData = response.data;
|
|
|
|
|
- const chartData = Object.entries(rawData).map(([name, value]) => ({
|
|
|
|
|
- name,
|
|
|
|
|
- value: parseFloat(value).toFixed(2)
|
|
|
|
|
- }));
|
|
|
|
|
-
|
|
|
|
|
- await this.$nextTick();
|
|
|
|
|
- const chartEl = this.$refs.barChartRef;
|
|
|
|
|
- if (chartEl) {
|
|
|
|
|
- this.barChartInstance = echarts.init(chartEl);
|
|
|
|
|
- const option = {
|
|
|
|
|
- title: { text: '部门效率分析', left: 'center' },
|
|
|
|
|
- tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, formatter: '{b}<br/>平均销售额: {c} 元' },
|
|
|
|
|
- grid: { left: '3%', right: '4%', bottom: '15%', containLabel: true },
|
|
|
|
|
- xAxis: { type: 'category', data: chartData.map(item => item.name), axisLabel: { rotate: 30, interval: 0 } },
|
|
|
|
|
- yAxis: { type: 'value', name: '平均销售额(元)' },
|
|
|
|
|
- series: [{
|
|
|
|
|
- name: '平均销售额',
|
|
|
|
|
- type: 'bar',
|
|
|
|
|
- data: chartData.map(item => item.value),
|
|
|
|
|
- barWidth: '40%',
|
|
|
|
|
- itemStyle: {
|
|
|
|
|
- borderRadius: [5, 5, 0, 0],
|
|
|
|
|
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
|
|
- { offset: 0, color: '#83bff6' },
|
|
|
|
|
- { offset: 1, color: '#188df0' }
|
|
|
|
|
- ])
|
|
|
|
|
- }
|
|
|
|
|
- }]
|
|
|
|
|
- };
|
|
|
|
|
- this.barChartInstance.setOption(option);
|
|
|
|
|
- }
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- this.barChart.error = err.message || '部门效率数据加载失败';
|
|
|
|
|
|
|
+ const response = await getShopDepartmentEfficiency()
|
|
|
|
|
+ const chartData = this.normalizeBarData(response)
|
|
|
|
|
+
|
|
|
|
|
+ await this.$nextTick()
|
|
|
|
|
+ const chart = this.initBarChartInstance()
|
|
|
|
|
+ if (!chart) return
|
|
|
|
|
+
|
|
|
|
|
+ chart.setOption({
|
|
|
|
|
+ title: { text: '部门效率分析', left: 'center' },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis',
|
|
|
|
|
+ axisPointer: { type: 'shadow' },
|
|
|
|
|
+ formatter: '{b}<br/>平均销售额: {c} 元'
|
|
|
|
|
+ },
|
|
|
|
|
+ grid: { left: '3%', right: '4%', bottom: '15%', containLabel: true },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ data: chartData.map(item => item.name),
|
|
|
|
|
+ axisLabel: { rotate: 30, interval: 0 }
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ name: '平均销售额(元)'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [{
|
|
|
|
|
+ name: '平均销售额',
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: chartData.map(item => Number(item.value.toFixed(2))),
|
|
|
|
|
+ barWidth: '40%',
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ borderRadius: [5, 5, 0, 0],
|
|
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
|
|
+ { offset: 0, color: '#83bff6' },
|
|
|
|
|
+ { offset: 1, color: '#188df0' }
|
|
|
|
|
+ ])
|
|
|
|
|
+ }
|
|
|
|
|
+ }]
|
|
|
|
|
+ }, true)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const message = this.getErrorMessage(error, '部门效率数据加载失败')
|
|
|
|
|
+ this.setChartStatus(
|
|
|
|
|
+ this.barChart,
|
|
|
|
|
+ this.isEmptyDataMessage(message) ? '暂无部门效率数据' : '部门效率数据加载失败',
|
|
|
|
|
+ this.isEmptyDataMessage(message) ? '请先在店铺价值页面上传 CSV 文件,再查看该图表。' : message,
|
|
|
|
|
+ !this.isEmptyDataMessage(message)
|
|
|
|
|
+ )
|
|
|
} finally {
|
|
} finally {
|
|
|
- this.barChart.loading = false;
|
|
|
|
|
|
|
+ this.barChart.loading = false
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
async initPieChart() {
|
|
async initPieChart() {
|
|
|
- this.pieChart.loading = true;
|
|
|
|
|
|
|
+ this.resetChartState(this.pieChart, '渠道多样性数据暂不可用')
|
|
|
try {
|
|
try {
|
|
|
- const response = await axios.get('/api/shop/import/channel-diversity');
|
|
|
|
|
- if (!response.data || !response.data.success) {
|
|
|
|
|
- throw new Error(response.data.message || '渠道多样性数据获取失败');
|
|
|
|
|
- }
|
|
|
|
|
- const rawData = response.data;
|
|
|
|
|
- const chartData = Object.entries(rawData).map(([name, value]) => ({ name, value }));
|
|
|
|
|
-
|
|
|
|
|
- await this.$nextTick();
|
|
|
|
|
- const chartEl = this.$refs.pieChartRef;
|
|
|
|
|
- if (chartEl) {
|
|
|
|
|
- this.pieChartInstance = echarts.init(chartEl);
|
|
|
|
|
- const option = {
|
|
|
|
|
- title: { text: '渠道商品多样性', left: 'center' },
|
|
|
|
|
- tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} ({d}%)' },
|
|
|
|
|
- legend: { orient: 'vertical', left: 'left', top: '10%' },
|
|
|
|
|
- series: [{
|
|
|
|
|
- name: '渠道',
|
|
|
|
|
- type: 'pie',
|
|
|
|
|
- radius: [20, 140],
|
|
|
|
|
- center: ['50%', '60%'],
|
|
|
|
|
- roseType: 'area',
|
|
|
|
|
- itemStyle: { borderRadius: 5 },
|
|
|
|
|
- data: chartData
|
|
|
|
|
- }]
|
|
|
|
|
- };
|
|
|
|
|
- this.pieChartInstance.setOption(option);
|
|
|
|
|
- }
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- this.pieChart.error = err.message || '渠道多样性数据加载失败';
|
|
|
|
|
|
|
+ const response = await getShopChannelDiversity()
|
|
|
|
|
+ const chartData = this.normalizePieData(response)
|
|
|
|
|
+
|
|
|
|
|
+ await this.$nextTick()
|
|
|
|
|
+ const chart = this.initPieChartInstance()
|
|
|
|
|
+ if (!chart) return
|
|
|
|
|
+
|
|
|
|
|
+ chart.setOption({
|
|
|
|
|
+ title: { text: '渠道商品多样性', left: 'center' },
|
|
|
|
|
+ tooltip: { trigger: 'item', formatter: '{a}<br/>{b}: {c} ({d}%)' },
|
|
|
|
|
+ legend: { orient: 'vertical', left: 'left', top: '10%' },
|
|
|
|
|
+ series: [{
|
|
|
|
|
+ name: '渠道',
|
|
|
|
|
+ type: 'pie',
|
|
|
|
|
+ radius: [20, 140],
|
|
|
|
|
+ center: ['50%', '60%'],
|
|
|
|
|
+ roseType: 'area',
|
|
|
|
|
+ itemStyle: { borderRadius: 5 },
|
|
|
|
|
+ data: chartData
|
|
|
|
|
+ }]
|
|
|
|
|
+ }, true)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const message = this.getErrorMessage(error, '渠道多样性数据加载失败')
|
|
|
|
|
+ this.setChartStatus(
|
|
|
|
|
+ this.pieChart,
|
|
|
|
|
+ this.isEmptyDataMessage(message) ? '暂无渠道多样性数据' : '渠道多样性数据加载失败',
|
|
|
|
|
+ this.isEmptyDataMessage(message) ? '请先在店铺价值页面上传 CSV 文件,再查看该图表。' : message,
|
|
|
|
|
+ !this.isEmptyDataMessage(message)
|
|
|
|
|
+ )
|
|
|
} finally {
|
|
} finally {
|
|
|
- this.pieChart.loading = false;
|
|
|
|
|
|
|
+ this.pieChart.loading = false
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
handleResize() {
|
|
handleResize() {
|
|
|
- if (this.barChartInstance) this.barChartInstance.resize();
|
|
|
|
|
- if (this.pieChartInstance) this.pieChartInstance.resize();
|
|
|
|
|
|
|
+ if (this.barChartInstance) {
|
|
|
|
|
+ this.barChartInstance.resize()
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.pieChartInstance) {
|
|
|
|
|
+ this.pieChartInstance.resize()
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
-
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
|
.department-efficiency-view {
|
|
.department-efficiency-view {
|
|
|
display: flex;
|
|
display: flex;
|
|
@@ -154,51 +255,64 @@ export default {
|
|
|
gap: 20px;
|
|
gap: 20px;
|
|
|
padding: 20px;
|
|
padding: 20px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.page-header {
|
|
.page-header {
|
|
|
padding: 15px 20px;
|
|
padding: 15px 20px;
|
|
|
- background-color: #ffffff;
|
|
|
|
|
|
|
+ background-color: #fff;
|
|
|
border-radius: 8px;
|
|
border-radius: 8px;
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.page-title {
|
|
.page-title {
|
|
|
margin: 0;
|
|
margin: 0;
|
|
|
font-size: 18px;
|
|
font-size: 18px;
|
|
|
font-weight: 600;
|
|
font-weight: 600;
|
|
|
color: #333;
|
|
color: #333;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.page-description {
|
|
.page-description {
|
|
|
margin: 4px 0 0;
|
|
margin: 4px 0 0;
|
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
|
color: #666;
|
|
color: #666;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.chart-area {
|
|
.chart-area {
|
|
|
position: relative;
|
|
position: relative;
|
|
|
padding: 20px;
|
|
padding: 20px;
|
|
|
- background-color: #ffffff;
|
|
|
|
|
|
|
+ background-color: #fff;
|
|
|
border-radius: 8px;
|
|
border-radius: 8px;
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
|
min-height: 540px;
|
|
min-height: 540px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+.chart-canvas {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 500px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.status-overlay {
|
|
.status-overlay {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
- inset: 0; /* a shorthand for top, right, bottom, left */
|
|
|
|
|
|
|
+ inset: 0;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
- background-color: rgba(255, 255, 255, 0.8);
|
|
|
|
|
|
|
+ padding: 24px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.88);
|
|
|
border-radius: 8px;
|
|
border-radius: 8px;
|
|
|
z-index: 10;
|
|
z-index: 10;
|
|
|
color: #555;
|
|
color: #555;
|
|
|
font-size: 16px;
|
|
font-size: 16px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.status-overlay.error {
|
|
.status-overlay.error {
|
|
|
color: #f56c6c;
|
|
color: #f56c6c;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.error-message {
|
|
.error-message {
|
|
|
|
|
+ margin-top: 8px;
|
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
|
color: #999;
|
|
color: #999;
|
|
|
- margin-top: 8px;
|
|
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|
|
|
-// __MARKER__
|
|
|