소스 검색

首页图表

ymy 1 년 전
부모
커밋
f644338874

+ 200 - 0
npminstall-debug.log

@@ -0,0 +1,200 @@
+{
+  root: 'E:\\benyun\\oms',
+  registry: 'https://registry.npmmirror.com',
+  pkgs: [
+    {
+      name: '',
+      version: 'antv/g2',
+      type: 'git',
+      alias: undefined,
+      arg: [Result]
+    }
+  ],
+  production: false,
+  cacheStrict: false,
+  cacheDir: null,
+  env: {
+    npm_config_registry: 'https://registry.npmmirror.com',
+    npm_config_argv: '{"remain":[],"cooked":["--fix-bug-versions","--china","--userconfig=C:\\\\Users\\\\Administrator\\\\.cnpmrc","--disturl=https://cdn.npmmirror.com/binaries/node","--registry=https://registry.npmmirror.com","antv/g2","--save"],"original":["--fix-bug-versions","--china","--userconfig=C:\\\\Users\\\\Administrator\\\\.cnpmrc","--disturl=https://cdn.npmmirror.com/binaries/node","--registry=https://registry.npmmirror.com","antv/g2","--save"]}',
+    npm_config_user_agent: 'npminstall/7.6.0 npm/? node/v18.15.0 win32 x64',
+    NODE: 'D:\\nodejs\\node.exe',
+    npm_node_execpath: 'D:\\nodejs\\node.exe',
+    npm_execpath: 'D:\\nodejs\\node_global\\node_modules\\cnpm\\node_modules\\npminstall\\bin\\install.js',
+    npm_config_userconfig: 'C:\\Users\\Administrator\\.cnpmrc',
+    npm_config_disturl: 'https://cdn.npmmirror.com/binaries/node',
+    npm_config_r: 'https://registry.npmmirror.com',
+    COREPACK_NPM_REGISTRY: 'https://registry.npmmirror.com',
+    NODEJS_ORG_MIRROR: 'https://cdn.npmmirror.com/binaries/node',
+    NVM_NODEJS_ORG_MIRROR: 'https://cdn.npmmirror.com/binaries/node',
+    PHANTOMJS_CDNURL: 'https://cdn.npmmirror.com/binaries/phantomjs',
+    CHROMEDRIVER_CDNURL: 'https://cdn.npmmirror.com/binaries/chromedriver',
+    OPERADRIVER_CDNURL: 'https://cdn.npmmirror.com/binaries/operadriver',
+    CYPRESS_DOWNLOAD_PATH_TEMPLATE: 'https://cdn.npmmirror.com/binaries/cypress/${version}/${platform}-${arch}/cypress.zip',
+    ELECTRON_MIRROR: 'https://cdn.npmmirror.com/binaries/electron/',
+    ELECTRON_BUILDER_BINARIES_MIRROR: 'https://cdn.npmmirror.com/binaries/electron-builder-binaries/',
+    SASS_BINARY_SITE: 'https://cdn.npmmirror.com/binaries/node-sass',
+    SWC_BINARY_SITE: 'https://cdn.npmmirror.com/binaries/node-swc',
+    NWJS_URLBASE: 'https://cdn.npmmirror.com/binaries/nwjs/v',
+    PUPPETEER_DOWNLOAD_HOST: 'https://cdn.npmmirror.com/binaries/chrome-for-testing',
+    PUPPETEER_DOWNLOAD_BASE_URL: 'https://cdn.npmmirror.com/binaries/chrome-for-testing',
+    PLAYWRIGHT_DOWNLOAD_HOST: 'https://cdn.npmmirror.com/binaries/playwright',
+    SENTRYCLI_CDNURL: 'https://cdn.npmmirror.com/binaries/sentry-cli',
+    SAUCECTL_INSTALL_BINARY_MIRROR: 'https://cdn.npmmirror.com/binaries/saucectl',
+    RE2_DOWNLOAD_MIRROR: 'https://cdn.npmmirror.com/binaries/node-re2',
+    RE2_DOWNLOAD_SKIP_PATH: 'true',
+    PRISMA_ENGINES_MIRROR: 'https://cdn.npmmirror.com/binaries/prisma',
+    npm_config_better_sqlite3_binary_host: 'https://cdn.npmmirror.com/binaries/better-sqlite3',
+    npm_config_keytar_binary_host: 'https://cdn.npmmirror.com/binaries/keytar',
+    npm_config_sharp_binary_host: 'https://cdn.npmmirror.com/binaries/sharp',
+    npm_config_sharp_libvips_binary_host: 'https://cdn.npmmirror.com/binaries/sharp-libvips',
+    npm_config_robotjs_binary_host: 'https://cdn.npmmirror.com/binaries/robotjs',
+    npm_rootpath: 'E:\\benyun\\oms',
+    INIT_CWD: 'E:\\benyun\\oms',
+    npm_config_cache: 'C:\\Users\\Administrator\\.npminstall_tarball'
+  },
+  binaryMirrors: {
+    ENVS: {
+      COREPACK_NPM_REGISTRY: 'https://registry.npmmirror.com',
+      NODEJS_ORG_MIRROR: 'https://cdn.npmmirror.com/binaries/node',
+      NVM_NODEJS_ORG_MIRROR: 'https://cdn.npmmirror.com/binaries/node',
+      PHANTOMJS_CDNURL: 'https://cdn.npmmirror.com/binaries/phantomjs',
+      CHROMEDRIVER_CDNURL: 'https://cdn.npmmirror.com/binaries/chromedriver',
+      OPERADRIVER_CDNURL: 'https://cdn.npmmirror.com/binaries/operadriver',
+      CYPRESS_DOWNLOAD_PATH_TEMPLATE: 'https://cdn.npmmirror.com/binaries/cypress/${version}/${platform}-${arch}/cypress.zip',
+      ELECTRON_MIRROR: 'https://cdn.npmmirror.com/binaries/electron/',
+      ELECTRON_BUILDER_BINARIES_MIRROR: 'https://cdn.npmmirror.com/binaries/electron-builder-binaries/',
+      SASS_BINARY_SITE: 'https://cdn.npmmirror.com/binaries/node-sass',
+      SWC_BINARY_SITE: 'https://cdn.npmmirror.com/binaries/node-swc',
+      NWJS_URLBASE: 'https://cdn.npmmirror.com/binaries/nwjs/v',
+      PUPPETEER_DOWNLOAD_HOST: 'https://cdn.npmmirror.com/binaries/chrome-for-testing',
+      PUPPETEER_DOWNLOAD_BASE_URL: 'https://cdn.npmmirror.com/binaries/chrome-for-testing',
+      PLAYWRIGHT_DOWNLOAD_HOST: 'https://cdn.npmmirror.com/binaries/playwright',
+      SENTRYCLI_CDNURL: 'https://cdn.npmmirror.com/binaries/sentry-cli',
+      SAUCECTL_INSTALL_BINARY_MIRROR: 'https://cdn.npmmirror.com/binaries/saucectl',
+      RE2_DOWNLOAD_MIRROR: 'https://cdn.npmmirror.com/binaries/node-re2',
+      RE2_DOWNLOAD_SKIP_PATH: 'true',
+      PRISMA_ENGINES_MIRROR: 'https://cdn.npmmirror.com/binaries/prisma',
+      npm_config_better_sqlite3_binary_host: 'https://cdn.npmmirror.com/binaries/better-sqlite3',
+      npm_config_keytar_binary_host: 'https://cdn.npmmirror.com/binaries/keytar',
+      npm_config_sharp_binary_host: 'https://cdn.npmmirror.com/binaries/sharp',
+      npm_config_sharp_libvips_binary_host: 'https://cdn.npmmirror.com/binaries/sharp-libvips',
+      npm_config_robotjs_binary_host: 'https://cdn.npmmirror.com/binaries/robotjs'
+    },
+    '@ali/s2': { host: 'https://cdn.npmmirror.com/binaries/looksgood-s2' },
+    sharp: { replaceHostFiles: [Array], replaceHostMap: [Object] },
+    '@tensorflow/tfjs-node': {
+      replaceHostFiles: [Array],
+      replaceHostRegExpMap: [Object],
+      replaceHostMap: [Object]
+    },
+    cypress: {
+      host: 'https://cdn.npmmirror.com/binaries/cypress',
+      newPlatforms: [Object]
+    },
+    'utf-8-validate': {
+      host: 'https://cdn.npmmirror.com/binaries/utf-8-validate/v{version}'
+    },
+    xprofiler: {
+      remote_path: './xprofiler/v{version}/',
+      host: 'https://cdn.npmmirror.com/binaries'
+    },
+    leveldown: { host: 'https://cdn.npmmirror.com/binaries/leveldown/v{version}' },
+    couchbase: { host: 'https://cdn.npmmirror.com/binaries/couchbase/v{version}' },
+    gl: { host: 'https://cdn.npmmirror.com/binaries/gl/v{version}' },
+    sqlite3: {
+      host: 'https://cdn.npmmirror.com/binaries/sqlite3',
+      remote_path: 'v{version}'
+    },
+    '@journeyapps/sqlcipher': { host: 'https://cdn.npmmirror.com/binaries' },
+    grpc: {
+      host: 'https://cdn.npmmirror.com/binaries',
+      remote_path: '{name}/v{version}'
+    },
+    'grpc-tools': { host: 'https://cdn.npmmirror.com/binaries' },
+    wrtc: {
+      host: 'https://cdn.npmmirror.com/binaries',
+      remote_path: '{name}/v{version}'
+    },
+    fsevents: { host: 'https://cdn.npmmirror.com/binaries/fsevents' },
+    nodejieba: { host: 'https://cdn.npmmirror.com/binaries/nodejieba' },
+    canvas: { host: 'https://cdn.npmmirror.com/binaries/canvas' },
+    'skia-canvas': { host: 'https://cdn.npmmirror.com/binaries/skia-canvas' },
+    'flow-bin': {
+      replaceHost: 'https://github.com/facebook/flow/releases/download/v',
+      host: 'https://cdn.npmmirror.com/binaries/flow/v'
+    },
+    'jpegtran-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/jpegtran-bin'
+    },
+    'cwebp-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/cwebp-bin'
+    },
+    'zopflipng-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/zopflipng-bin'
+    },
+    'optipng-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/optipng-bin'
+    },
+    mozjpeg: {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/mozjpeg-bin'
+    },
+    gifsicle: {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/gifsicle-bin'
+    },
+    'pngquant-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/pngquant-bin',
+      replaceHostMap: [Object]
+    },
+    'pngcrush-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/pngcrush-bin'
+    },
+    'jpeg-recompress-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/jpeg-recompress-bin'
+    },
+    'advpng-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/advpng-bin'
+    },
+    'pngout-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/pngout-bin'
+    },
+    'jpegoptim-bin': {
+      replaceHost: [Array],
+      host: 'https://cdn.npmmirror.com/binaries/jpegoptim-bin'
+    },
+    argon2: { host: 'https://cdn.npmmirror.com/binaries/argon2' },
+    'ali-zeromq': { host: 'https://cdn.npmmirror.com/binaries/ali-zeromq' },
+    'ali-usb_ctl': { host: 'https://cdn.npmmirror.com/binaries/ali-usb_ctl' },
+    'gdal-async': { host: 'https://cdn.npmmirror.com/binaries/node-gdal-async' }
+  },
+  forbiddenLicenses: null,
+  flatten: false,
+  proxy: undefined,
+  prune: false,
+  disableFallbackStore: false,
+  workspacesMap: Map(0) {},
+  enableWorkspace: false,
+  workspaceRoot: 'E:\\benyun\\oms',
+  isWorkspaceRoot: true,
+  isWorkspacePackage: false,
+  strictSSL: true,
+  ignoreScripts: false,
+  ignoreOptionalDependencies: false,
+  detail: false,
+  forceLinkLatest: false,
+  trace: false,
+  engineStrict: false,
+  registryOnly: false,
+  client: false,
+  autoFixVersion: [Function: autoFixVersion]
+}

+ 4 - 0
package.json

@@ -8,9 +8,12 @@
     "build:stage": "vue-cli-service build --mode staging"
   },
   "dependencies": {
+    "@antv/data-set": "^0.11.8",
+    "@antv/g2": "^4.2.10",
     "axios": "^1.3.5",
     "clipboard": "^2.0.11",
     "core-js": "^3.8.3",
+    "echarts": "^5.4.2",
     "element-ui": "^2.15.13",
     "file-saver": "^2.0.5",
     "fuse.js": "^6.6.2",
@@ -21,6 +24,7 @@
     "nprogress": "^0.2.0",
     "register-service-worker": "^1.7.2",
     "screenfull": "^5.0.2",
+    "script-ext-html-webpack-plugin": "^2.1.5",
     "svg-sprite-loader": "^6.0.11",
     "uuid": "^9.0.0",
     "vue": "^2.6.14",

+ 121 - 0
src/benyun/components/chart/columnarChart.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="box">
+    <div :id="id"></div>
+  </div>
+</template>
+
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import { Chart } from "@antv/g2";
+// declare const G2: any
+
+@Component
+export default class ColumnarChart extends Vue {
+  name='columnarChart';
+  @Prop()
+  propConfig:any
+
+  id = '';
+  chart:any = null;
+  created(){
+    this.id = this.randomString();
+  }
+  mounted(){
+    this.setConfig(this.propConfig)
+  }
+  randomString(){
+    const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    let result = '';
+    for (let i = 10; i > 0; --i) 
+      result += str[Math.floor(Math.random() * str.length)];
+    return result;
+  }
+
+  setConfig(config:any){
+    if(this.chart){
+      this.chart.destroy();
+      this.chart = null;
+    }
+    const w = (document.getElementById(this.id) as any).offsetWidth;
+    const h = (document.getElementById(this.id) as any).offsetHeight;
+    // Step 1: 创建 Chart 对象
+    this.chart = new Chart({
+      container: this.id, // 指定图表容器 ID
+      autoFit: true,
+      padding:config.padding?config.padding:null,
+      width : w, // 指定图表宽度
+      height : h, // 指定图表高度
+      
+    });
+    if(config.tooltip == false){
+      this.chart.tooltip(false);
+    }else if(config.tooltip){
+      this.chart.tooltip(config.tooltip);
+    }
+    if(config.transpose){
+      this.chart.coordinate().transpose()
+    }
+    if(config.legend){
+      this.chart.legend(config.legend)
+    }else{
+      this.chart.legend(false)
+    }
+    // Step 2: 载入数据源
+    this.chart.data(config.data)
+
+    if(config.axis){
+      for(const item of config.axis){
+        this.chart.axis(item.field,item.config)
+      }
+      
+    }
+    if(config.scale){
+      this.chart.scale(config.scale)
+    }
+    if(config.interaction){
+      this.chart.interaction(config.interaction)
+    }
+    // chart.source(config.data);
+    let initChart=this.chart.interval();
+    if(config.position){
+      initChart.position(config.position)
+    }
+    if(config.color){
+      initChart.color(config.color.field,config.color.list)
+    }
+    if(config.sales){
+      this.chart.sales(config.sales.field, config.sales.config);
+    }
+    if(config.label){
+      initChart.label(config.label.field,config.label.config)
+    }
+    if(config.adjust){
+      initChart.adjust(config.adjust)
+    }
+    
+    
+    // Step 4: 渲染图表
+    this.chart.render();
+    
+  }
+
+  setData(data:Array<any>){
+    if(this.chart){
+      this.chart.changeData(data)
+    }
+  }
+
+}
+
+</script>
+
+<style lang="scss" scoped>
+.box{
+  height: 100%;
+  width: 100%;
+  >div{
+    height: 100%;
+    width: 100%;
+  }
+}
+</style>

+ 121 - 0
src/benyun/components/chart/lineChart.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="box">
+    <div :id="id"></div>
+  </div>
+</template>
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import {Chart} from '@antv/g2';
+// import { Chart } from "@antv/g2";
+// declare const G2: any
+
+@Component
+export default class LineChart extends Vue {
+  name='lineChart';
+  @Prop()
+  propConfig:any
+  id = '';
+  chart:any = null;
+  created(){
+    this.id = this.randomString();
+  }
+  mounted(){
+    this.setConfig(this.propConfig)
+  }
+  randomString(){
+    const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    let result = '';
+    for (let i = 10; i > 0; --i) 
+      result += str[Math.floor(Math.random() * str.length)];
+    return result;
+  }
+  setConfig(config:any){
+    if(this.chart){
+      this.chart.destroy();
+      this.chart = null;
+    }
+    const w = (document.getElementById(this.id) as any).offsetWidth;
+    const h = (document.getElementById(this.id) as any).offsetHeight;
+    if(!this.chart){
+      this.chart = new Chart({
+        container: this.id,
+        height: h,
+        autoFit: true,
+        width:w,
+        padding:config.padding?config.padding:[20, 0, 20, 30]
+      });
+    }
+    if(config.tooltip == false){
+      this.chart.tooltip(false);
+    }else if(config.tooltip){
+      this.chart.tooltip(config.tooltip);
+    }
+    this.chart.legend(config.legend);
+    if(config.axis){
+      for(const item of config.axis){
+        this.chart.axis(item.field,item.config)
+      }
+    }
+    this.chart.data(config.data);
+    if(config.scale){
+      if(config.scale.field){
+        this.chart.scale(this.chart.scale.field,config.scale.config)
+      }else{
+        this.chart.scale(config.scale)
+      }
+    }
+
+    let initchart=this.chart.line();
+    if(config.position){
+      
+      initchart.position(config.position)
+      if(!config.pointClose){
+        this.chart.point().position(config.position);
+      }
+    }
+    if(config.size){
+      initchart.size(config.size)
+    }
+    if(config.shape){
+      initchart.shape(config.shape)
+    }
+    if(config.style){
+      initchart.style(config.style)
+    }
+    if(config.label){
+      initchart.label(config.label.field,config.label.config)
+    }
+    if(config.color){
+      initchart.color(config.color)
+    }
+    if (config.color) {
+      if(config.color.lists){
+        initchart.color(config.color.field, config.color.lists)
+      }else if(config.color.formatter){
+        initchart.color(config.color.field, config.color.formatter)
+      }else{
+        initchart.color(config.color)
+      }
+      
+    }
+    this.chart.render();
+  }
+
+  setData(data:Array<any>){
+    if(this.chart){
+      this.chart.changeData(data)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.box{
+  height: 100%;
+  width: 100%;
+  >div{
+    height: 100%;
+    width: 100%;
+  }
+}
+</style>

+ 120 - 0
src/benyun/components/chart/pieChart.vue

@@ -0,0 +1,120 @@
+<template>
+  <div class="box">
+    <div :id="id"></div>
+  </div>
+</template>
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import { Chart,Util } from '@antv/g2'
+// declare const G2: any
+
+@Component
+export default class PieChart extends Vue {
+  name = 'pieChart'
+  @Prop()
+  propConfig: any
+  id = ''
+  chart:any=null;
+  created() {
+    this.id = this.randomString()
+  }
+  mounted() {
+    this.$nextTick(() => {
+      this.setConfig(this.propConfig)
+    })
+  }
+  randomString() {
+    const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+    let result = ''
+    for (let i = 10; i > 0; --i) result += str[Math.floor(Math.random() * str.length)]
+    return result
+  }
+  setConfig(config:any) {
+    if(this.chart){
+      this.chart.destroy();
+      this.chart = null;
+    }
+    const w = (document.getElementById(this.id) as any).offsetWidth
+    const h = (document.getElementById(this.id) as any).offsetHeight
+    if(!this.chart){
+      this.chart = new Chart({
+        container: this.id,
+        autoFit: true,
+        padding:config.padding?config.padding:null,
+        height: h,
+        width: w
+      })
+    }
+    this.chart.legend(config.legend)
+    
+    this.chart.data(config.data)
+    if(config.guide){
+      this.chart.guide().html(config.guide.html);
+    }
+
+    const interval = this.chart
+      .interval()
+      .adjust('stack')
+      this.chart.interaction('element-single-selected');
+    if (config.coord) {
+      this.chart.coordinate('theta', config.coord.config)
+    } 
+    else {
+      this.chart.coordinate('theta', {
+        radius: 1
+      })
+    }
+
+    if(config.tooltip == false){
+      this.chart.tooltip(false);
+    }else if(config.tooltip){
+      this.chart.tooltip(config.tooltip);
+    }
+
+    if (config.position) {
+      interval.position(config.position)
+    }
+    if (config.color) {
+      if(config.color.lists){
+        interval.color(config.color.field, config.color.lists)
+      }else if(config.color.formatter){
+        interval.color(config.color.field, config.color.formatter)
+      }else{
+        interval.color(config.color.field)
+      }
+    }
+    if (config.label) {
+      if(config.label.formatter){
+        interval.label(config.label.field, config.label.formatter, config.label.config)
+      }else{
+        interval.label(config.label.field, config.label.config)
+      }
+    }
+    if (config.style) {
+      interval.style(config.style)
+    }
+    this.chart.render(true)
+  }
+
+  setData(data:Array<any>){
+    if(this.chart){
+      this.chart.changeData(data)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.box {
+  height: 100%;
+  width: 100%;
+  > div {
+    height: 100%;
+    width: 100%;
+  }
+}
+</style>
+
+<style lang="scss">
+
+</style>

+ 12 - 0
src/benyun/plugins/componentRegister.ts

@@ -51,6 +51,18 @@ const comps: Array<ComBase> = [
     name: "bySwitch",
     component: () => import("@/benyun/components/bySwitch/bySwitch.vue"),
   },
+  {
+    name: "columnarChart",
+    component: () => import("@/benyun/components/chart/columnarChart.vue"),
+  },
+  {
+    name: "lineChart",
+    component: () => import("@/benyun/components/chart/lineChart.vue"),
+  },
+  {
+    name: "pieChart",
+    component: () => import("@/benyun/components/chart/pieChart.vue"),
+  },
 ];
 
 const install = function (Vue: any) {

+ 72 - 0
src/views/components/bar01.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="chart" :id="id"></div>
+</template>
+
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import * as echarts from 'echarts';
+type EChartsOption = echarts.EChartsOption;
+
+@Component
+export default class Bar02 extends Vue {
+  id=this.randomString();
+
+  mounted(){
+    this.init()
+  }
+
+  randomString(){
+    const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    let result = '';
+    for (let i = 10; i > 0; --i) 
+      result += str[Math.floor(Math.random() * str.length)];
+    return result;
+  }
+
+  init(){
+    let chartDom:any = document.getElementById(this.id);
+    let myChart = echarts.init(chartDom);
+    let option: EChartsOption;
+
+    option = {
+      title: {
+        text: '每月订单量',
+        left: 'center'
+      },
+      xAxis: {
+        type: 'category',
+        data: ['7月', '8月', '9月', '10月', '11月', '12月', '1月','2月','3月','4月','5月','6月']
+      },
+      yAxis: {
+        type: 'value'
+      },
+      series: [
+        {
+          data: [0, 0, 0, 0, 0, 0, 0, 0, 0,100,460,600],
+          type: 'bar',
+          showBackground: true,
+          backgroundStyle: {
+            color: 'rgba(180, 180, 180, 0.2)'
+          },
+          itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              { offset: 0, color: '#83bff6' },
+              { offset: 0.5, color: '#188df0' },
+              { offset: 1, color: '#188df0' }
+            ])
+          }
+        }
+      ]
+    };
+
+    option && myChart.setOption(option);
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.chart{
+  height: 100%;
+  width: 100%;
+}
+</style>

+ 82 - 0
src/views/components/pie01.vue

@@ -0,0 +1,82 @@
+<template>
+  <div class="chart" :id="id"></div>
+</template>
+
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import * as echarts from 'echarts';
+type EChartsOption = echarts.EChartsOption;
+
+@Component
+export default class Pie01 extends Vue {
+  id=this.randomString();
+
+  mounted(){
+    this.init()
+  }
+
+  randomString(){
+    const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    let result = '';
+    for (let i = 10; i > 0; --i) 
+      result += str[Math.floor(Math.random() * str.length)];
+    return result;
+  }
+
+  init(){
+    let chartDom:any = document.getElementById(this.id);
+    let myChart = echarts.init(chartDom);
+    let option: EChartsOption;
+
+    option = {
+      title: {
+        text: '月区域订单量',
+        left: 'center'
+      },
+      tooltip: {
+        trigger: 'item'
+      },
+      legend: {
+        orient: 'vertical',
+        left: 'left'
+      },
+      series: [
+        {
+          name: 'Access From',
+          type: 'pie',
+          radius: '50%',
+          data:
+          [
+            {name:'北京市', value:3000},
+            {name:'广西壮族自治区', value:1000},
+            {name:'广东省',value:5500},
+            {name:'湖南省',value:2500},
+            {name:'贵州省',value:1300},
+            {name:'四川省',value:2600},
+            {name:'上海市',value:3600}
+          ],
+          emphasis: {
+            itemStyle: {
+              shadowBlur: 10,
+              shadowOffsetX: 0,
+              shadowColor: 'rgba(0, 0, 0, 0.5)'
+            }
+          },
+          label:{
+            formatter: '{b}: {d}' + '%'
+          }
+        }
+      ]
+    };
+
+    option && myChart.setOption(option);
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.chart{
+  height: 100%;
+  width: 100%;
+}
+</style>

+ 88 - 0
src/views/components/pie02.vue

@@ -0,0 +1,88 @@
+<template>
+  <div class="chart" :id="id"></div>
+</template>
+
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import * as echarts from 'echarts';
+type EChartsOption = echarts.EChartsOption;
+
+@Component
+export default class Pie02 extends Vue {
+  id=this.randomString();
+
+  mounted(){
+    this.init()
+  }
+
+  randomString(){
+    const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    let result = '';
+    for (let i = 10; i > 0; --i) 
+      result += str[Math.floor(Math.random() * str.length)];
+    return result;
+  }
+
+  init(){
+    let chartDom:any = document.getElementById(this.id);
+    let myChart = echarts.init(chartDom);
+    let option: EChartsOption;
+
+    option = {
+      title: {
+        text: '月订单来源',
+        left: 'center'
+      },
+      tooltip: {
+        trigger: 'item'
+      },
+      legend: {
+        orient: 'vertical',
+        right: 'right'
+      },
+      series: [
+        {
+          name: 'Access From',
+          type: 'pie',
+          radius: ['40%', '70%'],
+          avoidLabelOverlap: false,
+          itemStyle: {
+            borderRadius: 10,
+            borderColor: '#fff',
+            borderWidth: 2
+          },
+          label: {
+            formatter: '{b}:\n {d}' + '%',
+            position:'inside'
+          },
+          emphasis: {
+            label: {
+              show: true,
+              fontSize: 20,
+              fontWeight: 'bold'
+            }
+          },
+          labelLine: {
+            show: false
+          },
+          data: [
+            { value: 1048, name: '手工下单' },
+            { value: 735, name: '聚水潭' },
+            { value: 580, name: '其他' }
+          ]
+        }
+      ]
+    };
+
+    option && myChart.setOption(option);
+  }
+
+}
+</script>
+
+<style lang="scss" scoped>
+.chart{
+  height: 100%;
+  width: 100%;
+}
+</style>>

+ 82 - 0
src/views/components/rose.vue

@@ -0,0 +1,82 @@
+<template>
+  <div class="chart" :id="id"></div>
+</template>
+
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import * as echarts from 'echarts';
+type EChartsOption = echarts.EChartsOption;
+
+@Component
+export default class Rose extends Vue {
+  id=this.randomString();
+
+  mounted(){
+    this.init()
+  }
+
+  randomString(){
+    const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    let result = '';
+    for (let i = 10; i > 0; --i) 
+      result += str[Math.floor(Math.random() * str.length)];
+    return result;
+  }
+
+  init(){
+    let chartDom:any = document.getElementById(this.id);
+    let myChart = echarts.init(chartDom);
+    let option: EChartsOption;
+
+    option = {
+      title: {
+        text: '月订单状态',
+        left: 'center'
+      },
+      legend: {
+        top: 'bottom'
+      },
+      toolbox: {
+        show: true,
+        feature: {
+          mark: { show: true },
+          dataView: { show: true, readOnly: false },
+          restore: { show: true },
+          saveAsImage: { show: true }
+        }
+      },
+      series: [
+        {
+          name: 'Nightingale Chart',
+          type: 'pie',
+          radius: [30, 120],
+          center: ['50%', '50%'],
+          roseType: 'area',
+          itemStyle: {
+            borderRadius: 8
+          },
+          data: [
+            { value: 40, name: '待付款' },
+            { value: 38, name: '等待供应商|外仓发货' },
+            { value: 32, name: '已付款待审核' },
+            { value: 30, name: '已客审待财审' },
+            { value: 28, name: '发货中' },
+            { value: 26, name: '已发货' },
+            { value: 22, name: '取消订单' },
+            { value: 18, name: '订单异常' }
+          ]
+        }
+      ]
+    };
+
+    option && myChart.setOption(option);
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.chart{
+  height: 100%;
+  width: 100%;
+}
+</style>

+ 63 - 117
src/views/index.vue

@@ -1,129 +1,75 @@
 <template>
-  <div class="app-container home">
-    <el-row :gutter="20">
-      <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>SaaS协同平台</h2>
-        <p>
-          <b>当前版本:</b> <span>v{{ version }}</span>
-        </p>
-      </el-col>
-
-      <el-col :sm="24" :lg="12" style="padding-left: 50px">
-        <el-row>
-          <el-col :span="12">
-            <h2>技术选型</h2>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="6">
-            <h4>后端技术</h4>
-            <ul>
-              <li>SpringBoot</li>
-              <li>SpringCloud</li>
-              <li>Nacos</li>
-              <li>Sentinel</li>
-              <li>Seata</li>
-              <li>Minio</li>
-              <li>...</li>
-            </ul>
-          </el-col>
-          <el-col :span="6">
-            <h4>前端技术</h4>
-            <ul>
-              <li>Vue</li>
-              <li>Vuex</li>
-              <li>Element-ui</li>
-              <li>Axios</li>
-              <li>Echarts</li>
-              <li>Quill</li>
-              <li>...</li>
-            </ul>
-          </el-col>
-        </el-row>
-      </el-col>
-    </el-row>
-    <el-divider />
+  <div class="index-box">
+    <div class="index-row">
+      <div class="top-box">
+        <pie01 />
+      </div>
+      <div class="top-box">
+        <rose />
+      </div>
+      <div class="top-box">
+        <pie02 />
+      </div>
+    </div>
+    <div class="index-row">
+      <div class="bottom-box">
+        <bar01 />
+      </div>
+    </div>
   </div>
 </template>
 
-<script>
-export default {
-  name: "Index",
-  data() {
-    return {
-      // 版本号
-      version: "3.5.0",
-    };
-  },
-  methods: {
-    goTarget(href) {
-      window.open(href, "_blank");
-    },
-  },
-};
-</script>
-
-<style scoped lang="scss">
-.home {
-  blockquote {
-    padding: 10px 20px;
-    margin: 0 0 20px;
-    font-size: 17.5px;
-    border-left: 5px solid #eee;
-  }
-  hr {
-    margin-top: 20px;
-    margin-bottom: 20px;
-    border: 0;
-    border-top: 1px solid #eee;
-  }
-  .col-item {
-    margin-bottom: 20px;
-  }
-
-  ul {
-    padding: 0;
-    margin: 0;
-  }
-
-  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: 13px;
-  color: #676a6c;
-  overflow-x: hidden;
-
-  ul {
-    list-style-type: none;
-  }
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import pie01 from './components/pie01.vue'
+import rose from './components/rose.vue'
+import pie02 from './components/pie02.vue'
+import bar01 from './components/bar01.vue'
 
-  h4 {
-    margin-top: 0px;
-  }
+@Component({components:{pie01,rose,pie02,bar01}})
+export default class IndexView extends Vue {
 
-  h2 {
-    margin-top: 10px;
-    font-size: 26px;
-    font-weight: 100;
+  mounted(){
+    
   }
+}
+</script>
 
-  p {
-    margin-top: 10px;
-
-    b {
-      font-weight: 700;
+<style lang="scss" scoped>
+.index-box{
+  height: 100%;
+  width: 100%;
+  box-sizing: border-box;
+  padding: 16px;
+  .index-row{
+    height: 50%;
+    width: 100%;
+    display: flex;
+    box-sizing: border-box;
+    .top-box{
+      width: 33.33333%;
+      height: 100%;
+      box-sizing: border-box;
+      padding-right:8px;
     }
-  }
-
-  .update-log {
-    ol {
-      display: block;
-      list-style-type: decimal;
-      margin-block-start: 1em;
-      margin-block-end: 1em;
-      margin-inline-start: 0;
-      margin-inline-end: 0;
-      padding-inline-start: 40px;
+    .top-box:last-child{
+      padding: 0;
     }
+    .bottom-box{
+      width: 50%;
+      height: 100%;
+      box-sizing: border-box;
+      padding-right:8px
+    }
+    .bottom-box:last-child{
+      padding: 0;
+    }
+  }
+  .index-row:first-child{
+    padding-bottom: 8px;
+  }
+  .index-row:last-child{
+    padding-top: 8px;
   }
 }
-</style>
-
+</style>

+ 129 - 0
src/views/index2.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="app-container home">
+    <el-row :gutter="20">
+      <el-col :sm="24" :lg="12" style="padding-left: 20px">
+        <h2>SaaS协同平台</h2>
+        <p>
+          <b>当前版本:</b> <span>v{{ version }}</span>
+        </p>
+      </el-col>
+
+      <el-col :sm="24" :lg="12" style="padding-left: 50px">
+        <el-row>
+          <el-col :span="12">
+            <h2>技术选型</h2>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="6">
+            <h4>后端技术</h4>
+            <ul>
+              <li>SpringBoot</li>
+              <li>SpringCloud</li>
+              <li>Nacos</li>
+              <li>Sentinel</li>
+              <li>Seata</li>
+              <li>Minio</li>
+              <li>...</li>
+            </ul>
+          </el-col>
+          <el-col :span="6">
+            <h4>前端技术</h4>
+            <ul>
+              <li>Vue</li>
+              <li>Vuex</li>
+              <li>Element-ui</li>
+              <li>Axios</li>
+              <li>Echarts</li>
+              <li>Quill</li>
+              <li>...</li>
+            </ul>
+          </el-col>
+        </el-row>
+      </el-col>
+    </el-row>
+    <el-divider />
+  </div>
+</template>
+
+<script>
+export default {
+  name: "Index",
+  data() {
+    return {
+      // 版本号
+      version: "3.5.0",
+    };
+  },
+  methods: {
+    goTarget(href) {
+      window.open(href, "_blank");
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.home {
+  blockquote {
+    padding: 10px 20px;
+    margin: 0 0 20px;
+    font-size: 17.5px;
+    border-left: 5px solid #eee;
+  }
+  hr {
+    margin-top: 20px;
+    margin-bottom: 20px;
+    border: 0;
+    border-top: 1px solid #eee;
+  }
+  .col-item {
+    margin-bottom: 20px;
+  }
+
+  ul {
+    padding: 0;
+    margin: 0;
+  }
+
+  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 13px;
+  color: #676a6c;
+  overflow-x: hidden;
+
+  ul {
+    list-style-type: none;
+  }
+
+  h4 {
+    margin-top: 0px;
+  }
+
+  h2 {
+    margin-top: 10px;
+    font-size: 26px;
+    font-weight: 100;
+  }
+
+  p {
+    margin-top: 10px;
+
+    b {
+      font-weight: 700;
+    }
+  }
+
+  .update-log {
+    ol {
+      display: block;
+      list-style-type: decimal;
+      margin-block-start: 1em;
+      margin-block-end: 1em;
+      margin-inline-start: 0;
+      margin-inline-end: 0;
+      padding-inline-start: 40px;
+    }
+  }
+}
+</style>
+