| | |
| | | <template>
|
| | | <div class="app-container home">
|
| | | <div>
|
| | | <div>
|
| | | <div class="card-top-left">
|
| | | <div class="title">
|
| | | <span style="font-weight: bold">本月销售、采购情况计划</span>
|
| | | </div>
|
| | | <div class="card-group">
|
| | | <div class="info-card">
|
| | | <div class="info-message">
|
| | | <div class="info-number">6789,000</div>
|
| | | <div class="info-title">合同金额(元)</div>
|
| | | </div>
|
| | | <img src="@/assets/images/icon1.png" alt="" style="width: 63px;height: 63px">
|
| | | </div>
|
| | | <div class="info-card1">
|
| | | <div class="info-message">
|
| | | <div class="info-number">6789,000</div>
|
| | | <div class="info-title">开票金额(元)</div>
|
| | | </div>
|
| | | <img src="@/assets/images/icon2.png" alt="" style="width: 63px;height: 63px">
|
| | | </div>
|
| | | <div class="info-card2">
|
| | | <div class="info-message">
|
| | | <div class="info-number">6789,000</div>
|
| | | <div class="info-title">回款金额(元)</div>
|
| | | </div>
|
| | | <img src="@/assets/images/icon%203.png" alt="" style="width: 63px;height: 63px">
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | <div class="card-top-left">
|
| | | <div class="title">
|
| | | <span style="font-weight: bold">本月应收、应付情况计划</span>
|
| | | </div>
|
| | | <div class="pie">
|
| | | <div class="card-group">
|
| | | <div class="pie-group">
|
| | | <div style="margin-right: 80px">
|
| | | <Echarts ref="chart"
|
| | | :legend="pieLegend"
|
| | | :chartStyle="chartStyle"
|
| | | :series="materialPieSeries"
|
| | | :tooltip="pieTooltip"></Echarts>
|
| | | </div>
|
| | | <div class="info-message2">
|
| | | <div class="info-message1">
|
| | | <div class="pie-title">本月回款数量</div>
|
| | | <div class="pie-info"><span class="pie-number">8,000</span>元 <span class="pie-number">15.0</span>%</div>
|
| | | </div>
|
| | | <div class="info-message1">
|
| | | <div class="pie-title">应收款金额</div>
|
| | | <div class="pie-info"><span class="pie-number">8,000</span>元 <span class="pie-number">15.0</span>%</div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | <div class="card-group">
|
| | | <div class="pie-group">
|
| | | <div style="margin-right: 80px">
|
| | | <Echarts ref="chart"
|
| | | :options="options"
|
| | | :legend="pieLegend"
|
| | | :chartStyle="chartStyle"
|
| | | :series="materialPieSeries"
|
| | | :tooltip="pieTooltip"></Echarts>
|
| | | </div>
|
| | | <div class="info-message2">
|
| | | <div class="info-message1">
|
| | | <div class="pie-title">本月回款数量</div>
|
| | | <div class="pie-info"><span class="pie-number">8,000</span>元 <span class="pie-number">15.0</span>%</div>
|
| | | </div>
|
| | | <div class="info-message1">
|
| | | <div class="pie-title">应收款金额</div>
|
| | | <div class="pie-info"><span class="pie-number">8,000</span>元 <span class="pie-number">15.0</span>%</div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | <div></div>
|
| | | </div>
|
| | | <div>
|
| | | |
| | | </div>
|
| | | </div>
|
| | | </template>
|
| | |
|
| | | <script setup name="Index">
|
| | | import Echarts from "@/components/Echarts/echarts.vue";
|
| | |
|
| | | const pieLegend = reactive({
|
| | | show: false,
|
| | | })
|
| | | const options = reactive({
|
| | | graphic: {
|
| | | type: 'circle',
|
| | | left: 'center',
|
| | | top: 'middle',
|
| | | shape: {
|
| | | r: '70%' // 圆形半径与饼图外圈相同
|
| | | },
|
| | | style: {
|
| | | fill: 'none',
|
| | | stroke: '#ccc', // 灰色边框
|
| | | lineWidth: 2
|
| | | },
|
| | | z: -10 // 确保边框在饼图下面
|
| | | }
|
| | | })
|
| | | const pieTooltip = reactive({
|
| | | trigger: 'item',
|
| | | formatter: function (params) {
|
| | | // 动态生成提示信息,基于数据项的 name 属性
|
| | | const description = params.name === '本月回款数量' ? '本月回款数量' : '应收款金额';
|
| | | return `${description} ${formatNumber(params.value)}元 ${params.percent}%`;
|
| | | },
|
| | | position: 'right'
|
| | | })
|
| | | // 数字格式化函数,添加逗号作为千位分隔符
|
| | | function formatNumber(num) {
|
| | | return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
| | | }
|
| | | const materialPieSeries = ref([
|
| | | {
|
| | | type: 'pie',
|
| | | radius: '92%',
|
| | | avoidLabelOverlap: false,
|
| | | itemStyle: {
|
| | | borderColor: '#fff',
|
| | | borderWidth: 2
|
| | | },
|
| | | label: {
|
| | | show:false
|
| | | },
|
| | | data: [
|
| | | { value: 0, name: '本月回款数量', itemStyle: { color: '#2D99FF' } },
|
| | | { value: 0, name: '应收款金额', itemStyle: { color: '#D4DDFF' } },
|
| | | ]
|
| | | }
|
| | | ])
|
| | | const chartStyle = {
|
| | | width: '150%',
|
| | | height: '120%' // 设置图表容器的高度
|
| | | }
|
| | | </script>
|
| | |
|
| | | <style scoped>
|
| | | .card-top-left {
|
| | | padding: 16px;
|
| | | background: #fff;
|
| | | height: 24vh;
|
| | | width: 56vw;
|
| | | margin-bottom: 20px;
|
| | | }
|
| | | .title {
|
| | | position: relative;
|
| | | font-size: 18px;
|
| | | color: #333;
|
| | | font-weight: 400;
|
| | | padding-left: 10px;
|
| | | margin-bottom: 26px;
|
| | | }
|
| | | .title::before {
|
| | | position: absolute;
|
| | | left: 0;
|
| | | top: 4px;
|
| | | content: '';
|
| | | width: 4px;
|
| | | height: 18px;
|
| | | background-color: #3A7BFA;
|
| | | border-radius: 2px;
|
| | | }
|
| | | .card-group {
|
| | | display: flex;
|
| | | }
|
| | | .info-card {
|
| | | width: 300px;
|
| | | height: 126px;
|
| | | background-image: url("../assets/images/Rectangle 76@2x.png");
|
| | | background-size: 100% 100%;
|
| | | display: flex;
|
| | | justify-content: space-around;
|
| | | align-items: center;
|
| | | }
|
| | | .info-card1 {
|
| | | width: 300px;
|
| | | height: 126px;
|
| | | background-image: url("../assets/images/Rectangle 77@2x.png");
|
| | | background-size: 100% 100%;
|
| | | margin: 0 40px;
|
| | | display: flex;
|
| | | justify-content: space-around;
|
| | | align-items: center;
|
| | | }
|
| | | .info-card2 {
|
| | | width: 300px;
|
| | | height: 126px;
|
| | | background-image: url("../assets/images/Rectangle 77@2x(1).png");
|
| | | background-size: 100% 100%;
|
| | | display: flex;
|
| | | justify-content: space-around;
|
| | | align-items: center;
|
| | | }
|
| | | .info-message {
|
| | | display: flex;
|
| | | flex-direction: column;
|
| | | justify-content: center;
|
| | | align-items: center;
|
| | | }
|
| | | .info-message1 {
|
| | | font-weight: bold;
|
| | | display: flex;
|
| | | flex-direction: column;
|
| | | justify-content: center;
|
| | | align-items: flex-start;
|
| | | }
|
| | | .info-message2 {
|
| | | font-weight: bold;
|
| | | display: flex;
|
| | | flex-direction: column;
|
| | | align-items: center;
|
| | | justify-content: space-around;
|
| | | }
|
| | | .info-number {
|
| | | font-weight: bold;
|
| | | font-size: 32px;
|
| | | color: #FFFFFF;
|
| | | margin-bottom: 10px;
|
| | | }
|
| | | .info-title {
|
| | | font-weight: bold;
|
| | | font-size: 18px;
|
| | | color: #FFFFFF;
|
| | | }
|
| | | .pie {
|
| | | display: flex;
|
| | | flex-direction: row;
|
| | | justify-content: space-around;
|
| | | }
|
| | | .pie-group {
|
| | | display: flex;
|
| | | }
|
| | | .pie-title {
|
| | | font-size: 14px;
|
| | | line-height: 24px;
|
| | | color: #2853FD;
|
| | | padding-left: 16px;
|
| | | position: relative;
|
| | | }
|
| | | .pie-title::before {
|
| | | content: '';
|
| | | width: 6px; /* 蓝点的宽度 */
|
| | | height: 6px; /* 蓝点的高度 */
|
| | | background-color: #2853FD; /* 蓝点的颜色 */
|
| | | border-radius: 50%; /* 将正方形变为圆形 */
|
| | | position: absolute;
|
| | | left: 0; /* 定位到左边 */
|
| | | top: 9px; /* 垂直居中对齐,根据行高调整 */
|
| | | }
|
| | | .pie-info {
|
| | | padding-left: 16px;
|
| | | font-size: 14px;
|
| | | line-height: 24px;
|
| | | }
|
| | | .pie-number {
|
| | | color: #2853FD;
|
| | | }
|
| | | .info-group {
|
| | | display: flex;
|
| | | flex-direction: column;
|
| | | justify-content: center;
|
| | | align-items: center;
|
| | | }
|
| | | </style>
|
| | |
|
| | | <template> |
| | | <div class="dashboard"> |
| | | <!-- 顶部横向两栏 --> |
| | | <div class="dashboard-top"> |
| | | <!-- 左:企业信息+库存数据卡片(上下排列) --> |
| | | <div class="top-left"> |
| | | <div class="company-info"> |
| | | <!-- 顶部问候条 --> |
| | | <div class="welcome-banner"> |
| | | <div class="welcome-title"> |
| | | <span class="welcome-user">{{ userStore.nickName || '系统管理员' }}</span> |
| | | <span> 您好!祝您开心每一天</span> |
| | | </div> |
| | | <div class="welcome-time">登录于: {{ userStore.currentLoginTime }}</div> |
| | | </div> |
| | | |
| | | <!-- 用户信息卡片 --> |
| | | <div class="user-card"> |
| | | <img :src="userStore.avatar" class="avatar" alt="" /> |
| | | <div class="user-card-main"> |
| | | <div class="user-name">{{ userStore.name }}</div> |
| | | <div class="user-role">{{ userStore.roleName }}</div> |
| | | <div class="user-meta"> |
| | | <span>{{ userStore.phonenumber || '123456789' }}</span> |
| | | <span class="sep">|</span> |
| | | <span>{{ userStore.currentFactoryName || '组织架构' }}</span> |
| | | <span class="sep">|</span> |
| | | <span>{{ userStore.remark || '岗位名' }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 右:库存数据卡片 --> |
| | | <div class="data-cards"> |
| | | <div class="data-card inventory"> |
| | | <div class="data-title">库存数据</div> |
| | | <div class="data-num"> |
| | | <div> |
| | | <div class="data-desc">当前库存总量/件</div> |
| | | <div class="data-value">{{ businessInfo.inventoryNum }}</div> |
| | | </div> |
| | | <div> |
| | | <div class="data-desc">今日入库/件</div> |
| | | <div class="data-value">{{ businessInfo.todayInventoryNum }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue' |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import { getBusiness } from "@/api/viewIndex.js"; |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | | const businessInfo = ref({ |
| | | inventoryNum: 0, |
| | | todayInventoryNum: 0, |
| | | }) |
| | | |
| | | const getBusinessData = () => { |
| | | getBusiness().then((res) => { |
| | | businessInfo.value = { ...res.data } |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getBusinessData() |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .dashboard { |
| | | padding: 20px; |
| | | background: #f5f7fa; |
| | | min-height: calc(100vh - 84px); |
| | | } |
| | | |
| | | .dashboard-top { |
| | | display: grid; |
| | | grid-template-columns: 380px 1fr; |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | // 左侧用户信息 |
| | | .top-left { |
| | | .company-info { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04); |
| | | } |
| | | } |
| | | |
| | | .welcome-banner { |
| | | background: linear-gradient(135deg, var(--el-color-primary) 0%, var(--el-color-primary-light-3) 100%); |
| | | padding: 20px; |
| | | color: #fff; |
| | | |
| | | .welcome-title { |
| | | font-size: 16px; |
| | | margin-bottom: 8px; |
| | | |
| | | .welcome-user { |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | } |
| | | } |
| | | |
| | | .welcome-time { |
| | | font-size: 13px; |
| | | opacity: 0.9; |
| | | } |
| | | } |
| | | |
| | | .user-card { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 16px; |
| | | padding: 20px; |
| | | |
| | | .avatar { |
| | | width: 64px; |
| | | height: 64px; |
| | | border-radius: 50%; |
| | | object-fit: cover; |
| | | border: 3px solid var(--el-color-primary-light-8); |
| | | } |
| | | |
| | | .user-card-main { |
| | | flex: 1; |
| | | |
| | | .user-name { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .user-role { |
| | | font-size: 13px; |
| | | color: var(--el-color-primary); |
| | | background: var(--el-color-primary-light-9); |
| | | display: inline-block; |
| | | padding: 2px 10px; |
| | | border-radius: 12px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .user-meta { |
| | | font-size: 13px; |
| | | color: #909399; |
| | | |
| | | .sep { |
| | | margin: 0 8px; |
| | | color: #dcdfe6; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 右侧库存数据卡片 |
| | | .data-cards { |
| | | display: flex; |
| | | align-items: stretch; |
| | | } |
| | | |
| | | .data-card { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 24px; |
| | | box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04); |
| | | flex: 1; |
| | | |
| | | .data-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #606266; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 12px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .data-num { |
| | | display: flex; |
| | | gap: 40px; |
| | | |
| | | > div { |
| | | flex: 1; |
| | | } |
| | | |
| | | .data-desc { |
| | | font-size: 13px; |
| | | color: #909399; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .data-value { |
| | | font-size: 28px; |
| | | font-weight: 700; |
| | | color: #303133; |
| | | } |
| | | } |
| | | |
| | | &.inventory { |
| | | border-left: 4px solid var(--el-color-primary); |
| | | } |
| | | } |
| | | |
| | | // 响应式 |
| | | @media (max-width: 1200px) { |
| | | .dashboard-top { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .data-card .data-num { |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | } |
| | | </style> |