大數(shù)據(jù)項目代碼

主要文件:


image.png

各個文件內(nèi)的代碼:


image.png
// mock數(shù)據(jù)模擬
import Mock from 'mockjs'

// 圖表數(shù)據(jù)
let List = []

export default {
  getStatisticalData: () => {
    //Mock.Random.float 產(chǎn)生隨機數(shù)100到8000之間 保留小數(shù) 最小0位 最大0位
    for (let i = 0; i < 7; i++) {
      List.push(
        Mock.mock({
          蘋果: Mock.Random.float(100, 8000, 0, 0),
          vivo: Mock.Random.float(100, 8000, 0, 0),
          oppo: Mock.Random.float(100, 8000, 0, 0),
          魅族: Mock.Random.float(100, 8000, 0, 0),
          三星: Mock.Random.float(100, 8000, 0, 0),
          小米: Mock.Random.float(100, 8000, 0, 0)
        })
      )
    }

    return {
      code: 20000,
      data: {
        // 餅圖
        videoData: [
          {
            name: '小米',
            value: 2999
          },
          {
            name: '蘋果',
            value: 5999
          },
          {
            name: 'vivo',
            value: 1500
          },
          {
            name: 'oppo',
            value: 1999
          },
          {
            name: '魅族',
            value: 2200
          },
          {
            name: '三星',
            value: 4500
          }
        ],
        // 柱狀圖
        userData: [
          {
            date: '周一',
            new: 5,
            active: 200
          },
          {
            date: '周二',
            new: 10,
            active: 500
          },
          {
            date: '周三',
            new: 12,
            active: 550
          },
          {
            date: '周四',
            new: 60,
            active: 800
          },
          {
            date: '周五',
            new: 65,
            active: 550
          },
          {
            date: '周六',
            new: 53,
            active: 770
          },
          {
            date: '周日',
            new: 33,
            active: 170
          }
        ],
        // 折線圖
        orderData: {
          date: ['20191001', '20191002', '20191003', '20191004', '20191005', '20191006', '20191007'],
          data: List
        },

        tableData: [
          {
            name: 'oppo',
            todayBuy: 500,
            monthBuy: 3500,
            totalBuy: 22000
          },
          {
            name: 'vivo',
            todayBuy: 300,
            monthBuy: 2200,
            totalBuy: 24000
          },
          {
            name: '蘋果',
            todayBuy: 800,
            monthBuy: 4500,
            totalBuy: 65000
          },
          {
            name: '小米',
            todayBuy: 1200,
            monthBuy: 6500,
            totalBuy: 45000
          },
          {
            name: '三星',
            todayBuy: 300,
            monthBuy: 2000,
            totalBuy: 34000
          },
          {
            name: '魅族',
            todayBuy: 350,
            monthBuy: 3000,
            totalBuy: 22000
          }
        ]
      }
    }
  }
}

api/index.js

import http from "@/utils/request"

// 請求首頁數(shù)據(jù)
export const getDate = () => {
    // 會返回一個 promise 對象 
    return http.get('/home/getData')
}

api/mock.js

import Mock from 'mockjs'
import homeApi from '@/api/mockServeData/home'

// 定義mock請求攔截
// 請求地址   接口請求類型   處理函數(shù)
Mock.mock('/api/home/getData', 'get', homeApi.getStatisticalData)
image.png
<template>
    <el-menu
      default-active="1-4-1"
      class="el-menu-vertical-demo"
      @open="handleOpen"
      @close="handleClose"
      :collapse="isCollapse"
      active-text-color="#ffd04b"
      background-color="#545c64"
      text-color="#fff"
    >
    <h3>{{ isCollapse ? '后臺' : '通用后臺管理系統(tǒng)' }}</h3>
      <el-menu-item @click="cliclMenu(item)" v-for="item in noChildren" :key="item.name" :index="item.name">
        <i :class="`el-icon-${item.icon}`"></i>
        <span slot="title">{{ item.label }}</span>
      </el-menu-item>
  
      <el-submenu v-for="item in hasChildren" :key="item.label" :index="item.label">
        <template slot="title">
          <i :class="`el-icon-${item.icon}`"></i>
          <span slot="title">{{ item.label }}</span>
        </template>
        <el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
          <el-menu-item @click="cliclMenu(subItem)" :index="subItem.path">{{ subItem.label }}</el-menu-item>
        </el-menu-item-group>
      </el-submenu>
    </el-menu>
  </template>
  
  <script>
  export default {
    data() {
      return {
        menuData: [
          {
            path: "/",
            name: "home",
            label: "首頁",
            icon: "s-home",
            url: "Home/Home",
          },
          {
            path: "/mall",
            name: "mall",
            label: "商品管理",
            icon: "video-play",
            url: "MallManage/MallManage",
          },
          {
            path: "/user",
            name: "user",
            label: "用戶管理",
            icon: "user",
            url: "UserManage/UserManage",
          },
          {
            label: "其他",
            icon: "location",
            children: [
              {
                path: "/page1",
                name: "page1",
                label: "頁面1",
                icon: "setting",
                url: "Other/PageOne",
              },
              {
                path: "/page2",
                name: "page2",
                label: "頁面2",
                icon: "setting",
                url: "Other/PageTwo",
              },
            ],
          },
        ],
      };
    },
  
    methods: {
      handleOpen(key, keyPath) {
        console.log(key, keyPath);
      },
      handleClose(key, keyPath) {
        console.log(key, keyPath);
      },
      // 點擊菜單
      cliclMenu(item) {
        // 當頁面的路由與跳轉(zhuǎn)的路由路徑不一致的時候才允許跳轉(zhuǎn)
        if(this.$route.path !== item.path && !(this.$route.path === '/home' && (item.path === '/'))) {    // $route是路徑參數(shù)蓬抄,route 主要用于獲取當前路由信息
            this.$router.push(item.path)    // $router是路由對象,router 則是用于進行路由操作
        }    

      }
    },
  
    computed: {
      // 沒有子菜單
      noChildren() {
          return this.menuData.filter(item => !item.children)
      },
      // 有子菜單
      hasChildren() {
          return this.menuData.filter(item => item.children)
      },
      isCollapse() {
        return this.$store.state.tab.isCollapse
      }
    }
  };
  </script>
  
  <style lang="less" scoped>
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 200px;
    min-height: 400px;
  }
  .el-menu {
      height: 100vh;
      border-right: none;
      h3 {
          color: #fff;
          text-align: center;
          line-height: 48px;
          font-size: 16px;
          font-weight: 400px;
      }
  }
  </style>
image.png
<template>
    <div class="header-container">
        <div class="l-content">
            <el-button @click="handleMenu" icon="el-icon-menu" size="mini"></el-button>
            <!-- 面包屑 -->
            <span class="text">首頁</span>
        </div>
        <div class="r-content"> 
            <el-dropdown>
                <span class="el-dropdown-link">
                    <img class="user" src="@/assets/images/user.jpg">
                </span>
                <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item>個人中心</el-dropdown-item>
                    <el-dropdown-item>退出</el-dropdown-item>
                </el-dropdown-menu>
            </el-dropdown>
        </div>
    </div>
</template>

<script>
export default {
    data() {
      return { }
    },
    methods: {
        handleMenu() {
            this.$store.commit('collapseMenu')
        }
    }
}
</script>

<style lang="less" scoped>
.header-container {
    padding: 0px 20px;
    background-color: #333;
    height: 60px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .text {
        color: #fff;
        font-size: 14px;
        margin-left: 10px;
    }
    .r-content {
        .user {
            width: 40px;
            height: 40px;
            border-radius: 50px;
        }
    }
}
</style>
image.png
import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from '@/views/Home.vue'
import User from '@/views/User.vue'
import Mian from '@/views/Main.vue'
import Mall from '@/views/Mall.vue'
import PageOne from '@/views/PageOne.vue'
import PageTwo from '@/views/PageTwo.vue'
Vue.use(VueRouter)

const routes = [
  // 主路由
  {
    path: '/',
    component: Mian,
    redirect: '/home', //重定向
    children: [
      { path: '/home', component: Home },   //首頁
      { path: '/user', component: User },   //用戶管理
      { path: '/mall', component: Mall },   //商品管理
      { path: '/page1', component: PageOne },   //商品管理
      { path: '/page2', component: PageTwo },   //商品管理
    ]
  }
]

const router = new VueRouter({
    routes
})

export default router
image.png
import Vue from 'vue'
import Vuex from 'Vuex'

import tab from './tab'

Vue.use(Vuex)

// 創(chuàng)建vuex的實例
export default new Vuex.Store({
    modules: {
        tab
    }
})
image.png
// 管理菜單相關的數(shù)據(jù)
export default {
    state: {
        isCollapse: false   //用于控制菜單的展開還是收起
    },
    mutations: {
        // 修改菜單展開還是收起的方法
        collapseMenu(state) {
            state.isCollapse = !state.isCollapse
        }
    }
}
image.png
import axios from "axios"

const http = axios.create({ 
    // 通用請求地址前綴
    baseURL: '/api',
    timeout: 10000,  // 超時時間 10s
})

// 添加請求攔截器
http.interceptors.request.use(function (config) {
    // 在發(fā)送請求之前做些什么
    return config;
  }, function (error) {
    // 對請求錯誤做些什么
    return Promise.reject(error);
  });

// 添加響應攔截器
http.interceptors.response.use(function (response) {
    // 對響應數(shù)據(jù)做點什么
    return response;
  }, function (error) {
    // 對響應錯誤做點什么
    return Promise.reject(error);
  });

export default http
image.png
<template>
    <el-row>
        <el-col :span="8" style="padding-right: 10px">
            <el-card class="box-card">
                <div class="user">
                    <img src="@/assets/images/user.jpg">
                    <div class="userinfo">
                        <p class="name">Admin</p>
                        <p class="access">超級管理員</p>
                    </div>
                </div>
                <div class="login-info">
                    <p>上次登錄時間:<span>2023-12-8</span></p>
                    <p>上次登錄地點:<span>成都</span></p>
                </div>
            </el-card>

            <el-card style="margin-top: 20px; height: 460px">
                <el-table :data="tableData" style="width: 100%">
                    <el-table-column v-for="(val, key) in tableLabel" :key="key" :prop="key" :label="val">
                    </el-table-column>
                    <!-- <el-table-column prop="todayBuy" label="今日購買">
                    </el-table-column>
                    <el-table-column prop="monthBuy" label="本月購買">
                    </el-table-column>
                    <el-table-column prop="totalBuy" label="總購買">
                    </el-table-column> -->
                </el-table>
            </el-card>
        </el-col>

        <el-col :span="16" style="padding-left: 10px">
            <div class="num">
                <el-card v-for="item in countData" :key="item.name" :body-style="{ display: 'flex', padding: 0 }">
                    <i class="icon" :class="`el-icon-${item.icon}`" :style="{ background: item.color }"></i>
                    <div class="detail">
                        <p class="price">¥{{ item.value }}</p>
                        <p class="desc">{{ item.name }}</p>
                    </div>
                </el-card>
            </div>
            <!-- 折線圖 -->
            <el-card style="height: 280px">
                <div ref="echarts1" style="height: 280px"></div>
            </el-card>

            <!-- 柱狀圖與餅狀圖 -->
            <div class="graph">
                <el-card style="height: 260px">
                    <div ref="echarts2" style="height: 260px"></div>
                </el-card>
                <el-card style="height: 260px">
                    <div ref="echarts3" style="height: 240px"></div>
                </el-card>
            </div>

        </el-col>
    </el-row>
</template>

<script>
import { getDate } from "@/api";
import * as echarts from 'echarts'
export default {
    data() {
        return {
            tableData: [],
            tableLabel: {
                name: '課程',
                todayBuy: '今日購買',
                monthBuy: '本月購買',
                totalBuy: '總購買'
            },
            countData: [
                {
                    name: "今日支付訂單",
                    value: 1234,
                    icon: "success",
                    color: "#2ec7c9",
                },
                {
                    name: "今日收藏訂單",
                    value: 210,
                    icon: "star-on",
                    color: "#ffb980",
                },
                {
                    name: "今日未支付訂單",
                    value: 1234,
                    icon: "s-goods",
                    color: "#5ab1ef",
                },
                {
                    name: "本月支付訂單",
                    value: 1234,
                    icon: "success",
                    color: "#2ec7c9",
                },
                {
                    name: "本月收藏訂單",
                    value: 210,
                    icon: "star-on",
                    color: "#ffb980",
                },
                {
                    name: "本月未支付訂單",
                    value: 1234,
                    icon: "s-goods",
                    color: "#5ab1ef",
                },
            ],
        }
    },
    mounted() {
        getDate().then(({ data }) => {
            const { tableData, userData, videoData } = data.data
            this.tableData = tableData

            //折線圖
            // 基于準備好的dom履羞,初始化echarts實例
            const echarts1 = echarts.init(this.$refs.echarts1)
            // 繪制圖表
            var echarts1Option = {}
            // 處理x軸
            const { orderData } = data.data
            const xAxis = Object.keys(orderData.data[0])
            const xAxisData = {
                data: xAxis
            }
            echarts1Option.title = {
                text: '課程數(shù)據(jù)'
            },
                echarts1Option.xAxis = xAxisData
            // 處理y軸
            echarts1Option.yAxis = {}
            //legend    用于與下面的data匹配數(shù)據(jù)
            echarts1Option.legend = xAxisData
            // series
            echarts1Option.series = []
            xAxis.forEach(key => {
                echarts1Option.series.push({
                    name: key,      // 圖上面的名稱識別每個數(shù)據(jù)
                    data: orderData.data.map(item => item[key]),    // 每個name的具體數(shù)據(jù)
                    type: 'line'    // 統(tǒng)計圖的類型
                })
            })
            // 使用剛指定的配置項和數(shù)據(jù)顯示圖表
            echarts1.setOption(echarts1Option)

            // 柱狀圖
            const echarts2 = echarts.init(this.$refs.echarts2)
            const echarts2Option = {
                legend: {
                    // 圖例文字顏色
                    textStyle: {
                        color: "#333",
                    },
                },
                grid: {
                    left: "20%",
                },
                // 提示框
                tooltip: {
                    trigger: "axis",
                },
                xAxis: {
                    type: "category", // 類目軸
                    data: userData.map(item => item.date),
                    axisLine: {
                        lineStyle: {
                            color: "#17b3a3",
                        },
                    },
                    axisLabel: {
                        interval: 0,
                        color: "#333",
                    },
                },
                yAxis: [
                    {
                        type: "value",
                        axisLine: {
                            lineStyle: {
                                color: "#17b3a3",
                            },
                        },
                    },
                ],
                color: ["#2ec7c9", "#b6a2de"],
                series: [
                    {
                        name: '新增用戶',
                        data: userData.map(item => item.new),
                        type: 'bar'
                    },
                    {
                        name: '活躍用戶',
                        data: userData.map(item => item.active),
                        type: 'bar'
                    }
                ],
            }
            echarts2.setOption(echarts2Option)

            // 餅狀圖
            const echarts3 = echarts.init(this.$refs.echarts3)
            const echarts3Option = {
                tooltip: {
                    trigger: "item",
                },
                color: [
                    "#0f78f4",
                    "#dd536b",
                    "#9462e5",
                    "#a6a6a6",
                    "#e1bb22",
                    "#39c362",
                    "#3ed1cf",
                ],
                series: [
                    {
                        data: videoData,
                        type: 'pie'
                    }
                ],
            }
            echarts3.setOption(echarts3Option)
        })
    }
}
</script>

<style lang="less" scoped>
.user {
    padding-bottom: 20px;
    margin-bottom: 20px;
    border-bottom: 1px solid #ccc;
    display: flex;
    align-items: center;

    img {
        width: 150px;
        height: 150px;
        border-radius: 50%;
        margin-right: 40px;
    }

    .userinfo {
        .name {
            font-size: 32px;
            margin-bottom: 10px;
        }

        .access {
            color: #999999;
        }
    }
}

.login-info {
    p {
        line-height: 28px;
        font-size: 14px;
        color: #999999;

        span {
            color: #666666;
            margin-left: 60px;
        }
    }
}

.num {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;

    .icon {
        width: 80px;
        height: 80px;
        font-size: 30px;
        text-align: center;
        line-height: 80px;
        color: #fff;
    }

    .detail {
        display: flex;
        flex-direction: column;
        justify-content: center;
        margin-left: 15px;

        .price {
            font-size: 30px;
            margin-bottom: 10px;
            line-height: 30px;
            height: 30px;
        }

        .desc {
            color: #999999;
            font-size: 14px;
            text-align: center;
        }
    }

    .el-card {
        width: 32%;
        margin-bottom: 20px;
    }
}

.graph {
    margin-top: 20px;
    display: flex;
    justify-content: space-between;

    .el-card {
        width: 48%;
    }
}
</style>
image.png
<template>
    <div>
        <div class="common-layout">
            <el-container>
            <el-aside width="auto">
                <!-- 左側(cè)區(qū)域 -->
                <common-aside />    
            </el-aside>

            <el-container>
                <!-- 頂部區(qū)域 -->
                <el-header>
                    <common-header />
                </el-header>

                <!-- 主體區(qū)域 -->
                <el-main><router-view></router-view></el-main>
            </el-container>
        </el-container>
    </div>
    </div>
  </template>
  
<script>
import CommonAside from '@/components/CommonAside.vue'
import CommonHeader from '@/components/CommonHeader.vue'

  export default {
      data() {
        return { }
      },
      components: {
        CommonAside,
        CommonHeader
      }
  }
</script>
  
<style scoped>
  .el-header {
    padding: 0
  }
</style>
image.png
<template>
    <h1>我是Mall</h1>
</template>

<script>
export default {
    data() {
      return { }
    }
}
</script>

<style>

</style>
image.png
<template>
    <h1>我是PageOne</h1>
</template>

<script>
export default {
    data() {
      return { }
    }
}
</script>

<style>

</style>
image.png
<template>
    <h1>我是PageTwo</h1>
</template>

<script>
export default {
    data() {
      return { }
    }
}
</script>

<style>

</style>
image.png
<template>
    <h1>我是User</h1>
</template>

<script>
export default {
    data() {
      return { }
    }
}
</script>

<style>

</style>
image.png
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>


export default {
  name: 'App',

}
</script>

<style lang="less">
  h3,html,body,p {
    margin: 0;
    padding: 0;
  }
</style>
image.png
// main.ts
import Vue from 'vue'
import App from './App.vue'
import router from './router'

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

import store from '@/store/index'

import '@/api/mock'

Vue.config.productionTip = false

Vue.use(ElementUI )

new Vue({
  store,
  router,
  render: h => h(App),
}).$mount('#app')

其他記錄:
利用mock后臺數(shù)據(jù)模擬:(沒有后端數(shù)據(jù),前端自己給自己提供數(shù)據(jù))

定義:前端模擬后端的工具,用于攔截前端發(fā)起的請求吧雹,返回數(shù)據(jù)

1骨杂、下載安裝 pnpm install mockjs

2涂身、定義mock請求攔截雄卷,在main.js中引入,在api/mock.js中配置

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛤售,一起剝皮案震驚了整個濱河市丁鹉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悴能,老刑警劉巖揣钦,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異漠酿,居然都是意外死亡冯凹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門炒嘲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宇姚,“玉大人,你說我怎么就攤上這事夫凸』肜停” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵夭拌,是天一觀的道長魔熏。 經(jīng)常有香客問我,道長鸽扁,這世上最難降的妖魔是什么蒜绽? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮桶现,結(jié)果婚禮上躲雅,老公的妹妹穿的比我還像新娘。我一直安慰自己巩那,他們只是感情好吏夯,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著即横,像睡著了一般噪生。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上东囚,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天跺嗽,我揣著相機與錄音,去河邊找鬼。 笑死桨嫁,一個胖子當著我的面吹牛植兰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播璃吧,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼楣导,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了畜挨?” 一聲冷哼從身側(cè)響起筒繁,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎巴元,沒想到半個月后毡咏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡逮刨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年呕缭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片修己。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡恢总,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出箩退,到底是詐尸還是另有隱情离熏,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布戴涝,位于F島的核電站滋戳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏啥刻。R本人自食惡果不足惜奸鸯,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望可帽。 院中可真熱鬧娄涩,春花似錦、人聲如沸映跟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽努隙。三九已至球恤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荸镊,已是汗流浹背咽斧。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工堪置, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人张惹。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓舀锨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親宛逗。 傳聞我的和親對象是個殘疾皇子坎匿,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容