Jelajahi Sumber

chore: 框架完善

wll8 5 bulan lalu
induk
melakukan
870a07b49e
20 mengubah file dengan 1183 tambahan dan 100 penghapusan
  1. 91 72
      README.md
  2. 12 0
      doc.md
  3. 1 0
      mm/.eslintignore
  4. 1 0
      mm/.prettierignore
  5. 19 0
      mm/api/index.js
  6. 65 0
      mm/mm.config.js
  7. 3 0
      mm/package.json
  8. 19 0
      mm/readme.md
  9. 19 0
      mm/util.js
  10. 3 0
      package.json
  11. 8 0
      src/config.js
  12. 44 0
      src/http/index.js
  13. 7 5
      src/main.js
  14. 25 1
      src/router/index.js
  15. 17 0
      src/util/index.js
  16. 1 1
      src/views/Brand.vue
  17. 68 0
      src/views/page1/index.vue
  18. 66 0
      src/views/page2/index.vue
  19. 66 0
      src/views/page3/index.vue
  20. 648 21
      yarn.lock

+ 91 - 72
README.md

@@ -1,40 +1,109 @@
-# 前言
+## 前言
 
 * 一个基于Vue前端框架和第三方图表库echarts构建的可视化大数据平台,通过vue项目构建、指令的灵活运用、组件封装、组件之间通信,使内部图表组件库可实现自由替换和组合。
 * 项目中部分前端库采用外部CDN引入,可以减少打包文件体积,加快页面渲染。
 * 可视化数据大屏展示对前端性能要求高,建议使用谷歌浏览器查看或开发,屏幕尺寸为1920px宽和1080px高是最佳效果。
 * 目前制作数据可视化大屏,前端比较流行的第三方库有:Echarts(百度),AntV(阿里),Highcharts(国外公司),D3.js(国外公司)。
-* 如果感觉还不错的话,老铁们是不是赏个★Star鼓励一哈,后续会持续更新和优化,也期待大家的交流。
 
 
-[在线效果演示](https://jackchen0120.github.io/vueDataV/)
-
-## 学习教程分上下篇
-* [(上)Vue+Echarts构建可视化大数据平台实战项目分享](https://54web3.cc/blog/induction-tutorial/vue-echarts-prev-section)
-* [(下)Vue+Echarts构建大数据可视化酷炫展示公司品牌实战项目分享](https://54web3.cc/blog/induction-tutorial/vue-echarts-next-section)
-
-# 效果截图
-
-## 登录界面
+## 开发
+- 位于 dev 分支
+- 请使用 less 编写样式
+- 技术栈
+  - vue2.6
+  - echarts4.7
+  - axios
+  - webpack
+  - ES6
+  - scss
+  - css3
+  - jquery
+  - iconfont
+
+``` sh
+yarn
+yarn mm
+yarn serve
+```
 
-<img src="https://github.com/jackchen0120/vueDataV/blob/master/public/img/login_0.png" width="900" alt="登录界面" />
-<img src="https://github.com/jackchen0120/vueDataV/blob/master/public/img/login_1.png" width="900" alt="登录界面" />
-<img src="https://github.com/jackchen0120/vueDataV/blob/master/public/img/login_2.png" width="900" alt="登录界面" />
+运行之后,访问地址:http://localhost:8081
 
-## 首页酷屏统计图
+## 发布
 
-<img src="https://github.com/jackchen0120/vueDataV/blob/master/public/img/dataV_1.png" width="900" alt="首页酷屏统计图" />
-<img src="https://github.com/jackchen0120/vueDataV/blob/master/public/img/dataV_2.png" width="900" alt="首页酷屏统计图" />
-<img src="https://github.com/jackchen0120/vueDataV/blob/master/public/img/dataV_3.png" width="900" alt="首页酷屏统计图" />
-<img src="https://github.com/jackchen0120/vueDataV/blob/master/public/img/dataV_4.png" width="900" alt="首页酷屏统计图" />
+``` sh
+yarn build
+```
 
-## 公司品牌介绍
+## 页面
+
+- 综合问览 http://localhost:8081/#/page1
+- 种植分析 http://localhost:8081/#/page2
+- 种植分析详情 http://localhost:8081/#/page3
+- 登录页 http://localhost:8081
+- 首页 http://localhost:8081/#/home
+- 公司介绍 http://localhost:8081/#/brand
+
+## 任务
+
+- 目标 -- 11月25号之前完成页面和模拟接口/数据
+- 分工
+  - 模拟接口和数据 -- 肖文华
+  - 综合问览 -- 刘成阳
+    - 地图 -- 徐云辉
+    - 不包含的内容
+      - 实时统计中的目标完成率表
+  - 种植分析 -- 徐云辉
+    - 不包含的内容
+      - 顶部条
+      - 本月移栽数量趋势
+      - 本年移栽数据趋势
+  - 种植分析详情 -- 肖文华
+    - 不包含的内容
+      - 顶部条
+      - 本月移栽数量趋势
+      - 本年移栽数据趋势
+
+## 仅供参考
+- datav http://datav.jiaminghi.com/guide/
+- echarts https://echarts.apache.org/examples/zh/index.html
+- 首页 http://localhost:8081/#/home
+- 公司介绍 http://localhost:8081/#/brand
+- 图表示例集
+  - https://echarts.apache.org/examples/zh/index.html
+  - http://chart.majh.top/
+  - https://echarts.zhangmuchen.top/#/index
+  - https://madeapie.com/#/examples
+- 功能示例
+  - http://www.htmleaf.com/Demo/201508082380.html
+  - https://echarts.zhangmuchen.top/#/detail?cid=3e3af-6681-01d4-9e8ae-3475649d
+  - https://echarts.zhangmuchen.top/#/detail?cid=ef808-0753-f28d-b9dbf-857232b3
+  - https://echarts.zhangmuchen.top/#/detail?cid=cc8db-77e6-1b92-a8b88-e8026e2a
+  - https://echarts.zhangmuchen.top/#/detail?cid=xomSYW64ff
+  - https://echarts.zhangmuchen.top/#/detail?cid=f5937-38f8-ac10-b0dd5-e36bd25c
+  - https://echarts.zhangmuchen.top/#/detail?cid=5e921-123f-ee83-8f550-d21ebe25
+  - https://echarts.zhangmuchen.top/#/detail?cid=xcyIqcHZDe
+  - https://echarts.zhangmuchen.top/#/detail?cid=c1732-f317-0e53-a4a00-82e8f168
+  - https://echarts.zhangmuchen.top/#/detail?cid=xQbO0oOmdg
+  - https://echarts.zhangmuchen.top/#/detail?cid=xjHG-ufzOD
+  - https://echarts.zhangmuchen.top/#/detail?cid=xbmSYGhnhK
+  - https://echarts.zhangmuchen.top/#/detail?cid=xMQNuAkUYq
+
+- [(上)Vue+Echarts构建可视化大数据平台实战项目分享](https://54web3.cc/blog/induction-tutorial/vue-echarts-prev-section)
+- [(下)Vue+Echarts构建大数据可视化酷炫展示公司品牌实战项目分享](https://54web3.cc/blog/induction-tutorial/vue-echarts-next-section)
+
+## 项目架构
 
-<img src="https://github.com/jackchen0120/vueDataV/blob/master/public/img/brand.png" width="900" alt="炫酷展示公司品牌" />
+- 登录界面抖动
+- 粒子动效
+- 背景图轮播
+- 自定义全局模态框
+- 自定义消息提示框
+- 酷屏首页组件库
+- 各种酷炫小部件
+- 炫酷展示公司品牌
 
 
 
-# 项目架构
 ```
 │  vue.config.js                     // webpack配置              
 ├─public
@@ -99,53 +168,3 @@
             Home.vue                  // 酷屏首页统计图
             Login.vue                 // 登录界面
 ```
-
-# 技术栈
-
-- vue2.6
-- echarts4.7
-- axios
-- webpack
-- ES6
-- scss
-- css3
-- jquery
-- iconfont
-
-# 功能模块
-
-- 登录界面抖动
-- 粒子动效
-- 背景图轮播
-- 自定义全局模态框
-- 自定义消息提示框
-- 酷屏首页组件库
-- 各种酷炫小部件
-- 炫酷展示公司品牌
-
-# 下载安装依赖
-
-```
-git clone https://github.com/jackchen0120/vueDataV.git
-cd vueDataV
-# 建议node版本使用 v12/v14
-yarn
-```
-
-## 开发模式
-
-```
-yarn serve
-```
-
-运行之后,访问地址:http://localhost:8081
-
-## 生产环境打包
-
-```
-yarn build
-```
-
-#### 获取更多项目实战经验及各种源码资源,请关注作者公众号:懒人码农
-
-<img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAyMC81LzEzLzE3MjBlM2U0ZmQ5NDZiZDQ?x-oss-process=image/format,png" width="430" alt="公众号二维码" />

+ 12 - 0
doc.md

@@ -0,0 +1,12 @@
+### 相关基础项目
+  - https://github.com/MrManYoYo/Vue-Screen-Component
+  - https://github.com/lizhensheng/vue-data-view
+  - https://github.com/colaiven/cola-designer
+  - https://github.com/ddiu8081/ChartFun
+  - https://github.com/yyhsong/iDataV
+  - https://github.com/bym110/vue-echarts
+  - https://github.com/TurboWay/big_screen
+  - https://github.com/Alfred-Skyblue/v-scale-screen
+  - https://github.com/food-billboard/create-chart
+  - https://github.com/zhangti0708/bigdata-examples
+  - https://github.com/iGaoWei/BigDataView

+ 1 - 0
mm/.eslintignore

@@ -0,0 +1 @@
+/**/*

+ 1 - 0
mm/.prettierignore

@@ -0,0 +1 @@
+/**/*

+ 19 - 0
mm/api/index.js

@@ -0,0 +1,19 @@
+const { wrapApiData } = require(`../util.js`)
+
+/** @type {import('mockm/@types/config').Config} */
+module.exports = util => {
+  const {
+    libObj: { mockjs },
+  } = util
+  return {
+    api: {
+      // 创建接口并使用 mockjs 生成数据
+      'get /api/test': wrapApiData(mockjs.mock({
+        'data|3-7': [{
+          userId: `@id`,
+          userName: `@cname`,
+        }],
+      })),
+    },
+  }
+}

+ 65 - 0
mm/mm.config.js

@@ -0,0 +1,65 @@
+const api = require(`./api/index.js`)
+const { wrapApiData } = require(`./util.js`)
+
+/**
+ * 配置说明请参考文档: 
+ * https://hongqiye.com/doc/mockm/config/option.html
+ * @type {import('mockm/@types/config').Config}
+ */
+module.exports = util => {
+  return {
+    guard: false,
+    port: 8100,
+    testPort: 8105,
+    replayPort: 8101,
+    watch: [`./api/`],
+    proxy: {
+      '/': `http://www.httpbin.org/`, // 后端接口主域
+      '/anything/intercept': [`origin`, `127.0.0.1`], // 修改接口返回的数据
+    },
+    api: {
+      // 在其他文件里的 api
+      ...api(util).api,
+      
+      // 当为基本数据类型时, 直接返回数据, 这个接口返回 {"msg":"ok"}
+      '/api/1': {msg: `ok`},
+
+      // 也可以像 express 一样返回数据
+      '/api/2' (req, res) {
+        res.send({msg: `ok`})
+      },
+
+      // 一个只能使用 post 方法访问的接口
+      'post /api/3': {msg: `ok`},
+
+      // // 一个 websocket 接口, 会发送收到的消息
+      // 'ws /api/4' (ws, req) {
+      //   ws.on('message', (msg) => ws.send(msg))
+      // },
+
+      // 一个下载文件的接口
+      '/file' (req, res) {
+        res.download(__filename, `mm.config.js`)
+      },
+
+      // 获取动态的接口路径的参数 code
+      '/status/:code' (req, res) {
+        res.json({statusCode: req.params.code})
+      },
+
+      // 使用 mockjs 生成数据
+      '/user' (req, res) {
+        const json = util.libObj.mockjs.mock({
+          'data|3-7': [{
+            userId: `@id`,
+            userName: `@cname`,
+          }],
+        })
+        res.json(json)
+      },
+    },
+    static: [],
+    resHandleReplay: ({req, res}) => wrapApiData({code: 200, data: {}}),
+    resHandleJsonApi: ({req, res: {statusCode: code}, data}) => wrapApiData({code, data}),
+  }
+}

+ 3 - 0
mm/package.json

@@ -0,0 +1,3 @@
+{
+  "type": "commonjs"
+}

+ 19 - 0
mm/readme.md

@@ -0,0 +1,19 @@
+# 说明
+
+此目录是运行命令 `mm --template` 之后生成的 mockm 常用配置, 该命令做了以下事情:
+
+在运行目录的 package.json 的 scripts 中添加命令 `"mm": "npx mockm --cwd=mm"`, 如果没有 package.json 文件, 会自动创建.
+
+创建名为 mm 的目录, 文件说明如下, 如果存在则不覆盖:
+
+```
+mm/
+  - api/ -- 手动创建的 api
+  - util.js -- 一些公用方法
+  - mm.config.js -- mockm 的配置文件
+```
+
+## 参考
+- [mm 代码仓库](https://github.com/wll8/mockm/)
+- [mm 文档](https://hongqiye.com/doc/mockm/)
+- [mockjs 文档](https://wll8.github.io/mockjs-examples/)

+ 19 - 0
mm/util.js

@@ -0,0 +1,19 @@
+/**
+ * 包裹 api 的返回值
+ * @param {*} param0
+ * @param {object} param0.data - 原始数据
+ * @param {number|string} [param0.code=200] - http状态码
+ * @returns
+ */
+function wrapApiData({data, code = 200}) {
+  code = String(code)
+  return {
+    code,
+    success: Boolean(code.match(/^[2]/)), // 如果状态码以2开头则为 true
+    data,
+  }
+}
+
+module.exports = {
+  wrapApiData,
+}

+ 3 - 0
package.json

@@ -5,10 +5,12 @@
   "author": "JackChen <278910933@qq.com>",
   "scripts": {
     "serve": "vue-cli-service serve",
+    "mm": "npx mockm",
     "build": "vue-cli-service build",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "axios": "^1.7.7",
     "core-js": "^3.6.4",
     "vue": "^2.6.11",
     "vue-router": "^3.1.6",
@@ -24,6 +26,7 @@
     "eslint-plugin-vue": "^6.2.2",
     "less": "^4.2.0",
     "less-loader": "6.x",
+    "mockm": "^1.1.27-alpha.9",
     "node-sass": "^4.13.1",
     "sass-loader": "^8.0.2",
     "vue-count-to": "^1.0.13",

+ 8 - 0
src/config.js

@@ -0,0 +1,8 @@
+export default {
+  development: {
+    baseApi: `http://localhost:8100`,
+  },
+  prod: {
+    baseApi: `http://127.0.0.1:8100`,
+  },
+}[process.env.NODE_ENV || `prod`]

+ 44 - 0
src/http/index.js

@@ -0,0 +1,44 @@
+import config from '@/config.js'
+import util from '@/util/index.js'
+
+const api =  window.axios.create({
+  timeout: 10000, // 请求超时
+  baseURL: config.baseApi,
+})
+
+// request拦截器
+api.interceptors.request.use(
+  (options) => {
+    options.baseURL = config.baseApi
+    return options
+  },
+  (error) => {
+    Promise.reject(error)
+  }
+)
+// response拦截器
+api.interceptors.response.use(
+  (response) => {
+    const data = response.data
+    if (util.isType(data, `blob`)) {
+      return response
+    } else if (data.data === undefined) {
+      return data
+    } else {
+      return response.data.data
+    }
+  },
+  (error) => {
+    return Promise.reject(error)
+  }
+)
+
+const install = (Vue) => {
+  Vue.prototype.$http = api
+}
+
+export { api }
+
+export default {
+  install,
+}

+ 7 - 5
src/main.js

@@ -1,4 +1,5 @@
 import Vue from 'vue'
+import http from '@/http/index.js'
 import App from './App.vue'
 import router from './router'
 import store from './store'
@@ -10,6 +11,7 @@ import '@/assets/styles/base.scss'
 import '@/assets/styles/common.scss'
 import '@/assets/iconfont/iconfont.css'
 
+Vue.use(http)
 Vue.use(vueParticles)
 Vue.use(Vcomp)
 
@@ -20,13 +22,13 @@ Vue.prototype.$Toast = Toast
 
 router.beforeEach((to, from, next) => {
 	if (to.meta.title) {
-	  document.title = to.meta.title;
+		document.title = to.meta.title;
 	}
 	next();
 })
 
-new Vue({
-  router,
-  store,
-  render: h => h(App),
+window.$this = new Vue({
+	router,
+	store,
+	render: h => h(App),
 }).$mount('#app')

+ 25 - 1
src/router/index.js

@@ -31,7 +31,31 @@ const routes = [
     meta: {
       title: '公司品牌介绍'
     }
-  }
+  },
+  {
+    path: '/page1',
+    name: 'page1',
+    component: () => import('@/views/page1/index.vue'),
+    meta: {
+      title: '综合问览'
+    }
+  },
+  {
+    path: '/page2',
+    name: 'page2',
+    component: () => import('@/views/page2/index.vue'),
+    meta: {
+      title: '种植分析'
+    }
+  },
+  {
+    path: '/page3',
+    name: 'page3',
+    component: () => import('@/views/page3/index.vue'),
+    meta: {
+      title: '种植分析详情'
+    }
+  },
 ]
 
 const router = new VueRouter({

+ 17 - 0
src/util/index.js

@@ -0,0 +1,17 @@
+/**
+ * 判断数据是否为 type, 或返回 type
+ * @param {*} data
+ * @param {*} type
+ * @returns
+ */
+function isType(data, type = undefined) {
+  const dataType = Object.prototype.toString
+    .call(data)
+    .match(/\s(.+)]/)[1]
+    .toLowerCase()
+  return type ? dataType === type.toLowerCase() : dataType
+}
+
+export default {
+  isType,
+}

+ 1 - 1
src/views/Brand.vue

@@ -179,7 +179,7 @@ export default {
       this.nowTimes = null;
     },
     getWeather() { // 第三方天气api接口
-      axios.get('https://www.tianqiapi.com/api/', {
+      window.axios.get('https://www.tianqiapi.com/api/', {
         params: {
           appid: '26148275',
           appsecret: '2id6H48Y',

+ 68 - 0
src/views/page1/index.vue

@@ -0,0 +1,68 @@
+<template>
+  <div class="home-container">
+    <div class="wrap" ref="editor">
+      <div class="top"></div>
+      <div class="box">一些内容</div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { screenSize } from "@/assets/js/utils";
+
+export default {
+  name: "Home",
+  components: {},
+  data() {
+    return {};
+  },
+  computed: {},
+  created() {
+    this.$http.get(`https://httpbin.org/get`)
+  },
+  mounted() {
+    screenSize(this.$refs.editor);
+  },
+  methods: {},
+};
+</script>
+
+<style lang="less" scoped>
+.home-container {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  .wrap {
+    transform-origin: 0px 0px 0px;
+    background: url(../../assets/img/bj.jpg) no-repeat;
+    background-size: contain;
+    background-position: 50% 0;
+    background-color: rgb(0, 0, 0);
+    min-width: auto;
+    width: 1920px;
+    min-height: auto;
+    height: 1080px;
+    overflow: auto;
+    .top {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 80px;
+      background-color: transparent;
+      background: url(../../assets/img/top_nav.png) no-repeat;
+      background-position: 65% 0;
+      border: none;
+      overflow: hidden;
+    }
+    .box {
+      color: #fff;
+      line-height: 100vh;
+      text-align: center;
+      font-size: 40px;
+    }
+  }
+}
+</style>

+ 66 - 0
src/views/page2/index.vue

@@ -0,0 +1,66 @@
+<template>
+  <div class="home-container">
+    <div class="wrap" ref="editor">
+      <div class="top"></div>
+      <div class="box">一些内容</div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { screenSize } from "@/assets/js/utils";
+
+export default {
+  name: "Home",
+  components: {},
+  data() {
+    return {};
+  },
+  computed: {},
+  created() {},
+  mounted() {
+    screenSize(this.$refs.editor);
+  },
+  methods: {},
+};
+</script>
+
+<style lang="less" scoped>
+.home-container {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  .wrap {
+    transform-origin: 0px 0px 0px;
+    background: url(../../assets/img/bj.jpg) no-repeat;
+    background-size: contain;
+    background-position: 50% 0;
+    background-color: rgb(0, 0, 0);
+    min-width: auto;
+    width: 1920px;
+    min-height: auto;
+    height: 1080px;
+    overflow: auto;
+    .top {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 80px;
+      background-color: transparent;
+      background: url(../../assets/img/top_nav.png) no-repeat;
+      background-position: 65% 0;
+      border: none;
+      overflow: hidden;
+    }
+    .box {
+      color: #fff;
+      line-height: 100vh;
+      text-align: center;
+      font-size: 40px;
+    }
+  }
+}
+</style>

+ 66 - 0
src/views/page3/index.vue

@@ -0,0 +1,66 @@
+<template>
+  <div class="home-container">
+    <div class="wrap" ref="editor">
+      <div class="top"></div>
+      <div class="box">一些内容</div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { screenSize } from "@/assets/js/utils";
+
+export default {
+  name: "Home",
+  components: {},
+  data() {
+    return {};
+  },
+  computed: {},
+  created() {},
+  mounted() {
+    screenSize(this.$refs.editor);
+  },
+  methods: {},
+};
+</script>
+
+<style lang="less" scoped>
+.home-container {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  .wrap {
+    transform-origin: 0px 0px 0px;
+    background: url(../../assets/img/bj.jpg) no-repeat;
+    background-size: contain;
+    background-position: 50% 0;
+    background-color: rgb(0, 0, 0);
+    min-width: auto;
+    width: 1920px;
+    min-height: auto;
+    height: 1080px;
+    overflow: auto;
+    .top {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 80px;
+      background-color: transparent;
+      background: url(../../assets/img/top_nav.png) no-repeat;
+      background-position: 65% 0;
+      border: none;
+      overflow: hidden;
+    }
+    .box {
+      color: #fff;
+      line-height: 100vh;
+      text-align: center;
+      font-size: 40px;
+    }
+  }
+}
+</style>

File diff ditekan karena terlalu besar
+ 648 - 21
yarn.lock


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini