chart and table
diff --git a/package-lock.json b/package-lock.json
index d067e4d..c489f7f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,16 @@
"resolved": "https://registry.nlark.com/@babel/parser/download/@babel/parser-7.14.3.tgz?cache=0&sync_timestamp=1621284389691&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.14.3.tgz",
"integrity": "sha1-m1MO7LBx/QyTUZ3yXF/58UdZ8pg="
},
+ "@babel/polyfill": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npm.taobao.org/@babel/polyfill/download/@babel/polyfill-7.12.1.tgz",
+ "integrity": "sha1-Hy1jcdEmG72WHzxdWQkVDhLQvZY=",
+ "dev": true,
+ "requires": {
+ "core-js": "^2.6.5",
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
"@babel/types": {
"version": "7.14.2",
"resolved": "https://registry.nlark.com/@babel/types/download/@babel/types-7.14.2.tgz",
@@ -403,6 +413,15 @@
"@types/node": "*"
}
},
+ "@types/jquery": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz",
+ "integrity": "sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==",
+ "dev": true,
+ "requires": {
+ "@types/sizzle": "*"
+ }
+ },
"@types/lodash": {
"version": "4.14.169",
"resolved": "https://registry.nlark.com/@types/lodash/download/@types/lodash-4.14.169.tgz",
@@ -420,6 +439,12 @@
"integrity": "sha1-I6Brh+7bUkAWYW6IaxFrj9yxgK8=",
"dev": true
},
+ "@types/sizzle": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
+ "dev": true
+ },
"@types/unist": {
"version": "2.0.3",
"resolved": "https://registry.nlark.com/@types/unist/download/@types/unist-2.0.3.tgz?cache=0&sync_timestamp=1621243829208&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Funist%2Fdownload%2F%40types%2Funist-2.0.3.tgz",
@@ -790,6 +815,11 @@
"integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=",
"dev": true
},
+ "bignumber.js": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npm.taobao.org/bignumber.js/download/bignumber.js-8.1.1.tgz",
+ "integrity": "sha1-Swcq5a6pwg9nMOTl1SnfEnHE2IU="
+ },
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.2.0.tgz?cache=0&sync_timestamp=1610299293319&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbinary-extensions%2Fdownload%2Fbinary-extensions-2.2.0.tgz",
@@ -1278,6 +1308,12 @@
"@babel/types": "^7.6.1"
}
},
+ "core-js": {
+ "version": "2.6.12",
+ "resolved": "https://registry.nlark.com/core-js/download/core-js-2.6.12.tgz",
+ "integrity": "sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw=",
+ "dev": true
+ },
"core-util-is": {
"version": "1.0.2",
"resolved": "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz",
@@ -1500,6 +1536,15 @@
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
"dev": true
},
+ "echarts": {
+ "version": "5.1.1",
+ "resolved": "https://registry.nlark.com/echarts/download/echarts-5.1.1.tgz",
+ "integrity": "sha1-sYbxYvAXxVXP1nsS7eZ2K9w939o=",
+ "requires": {
+ "tslib": "2.0.3",
+ "zrender": "5.1.0"
+ }
+ },
"electron-to-chromium": {
"version": "1.3.747",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.747.tgz",
@@ -1861,6 +1906,16 @@
"integrity": "sha1-/wQLKwhTsjw9MQJ1I3BvGIXXa+4=",
"dev": true
},
+ "handsontable": {
+ "version": "6.2.2",
+ "resolved": "https://registry.nlark.com/handsontable/download/handsontable-6.2.2.tgz?cache=0&sync_timestamp=1622544081773&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhandsontable%2Fdownload%2Fhandsontable-6.2.2.tgz",
+ "integrity": "sha1-8SUPPzdKvffUoAgJUEgtPt7qjwc=",
+ "requires": {
+ "moment": "2.20.1",
+ "numbro": "^2.0.6",
+ "pikaday": "1.5.1"
+ }
+ },
"has": {
"version": "1.0.3",
"resolved": "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz",
@@ -2275,6 +2330,11 @@
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
+ "jquery": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npm.taobao.org/jquery/download/jquery-3.6.0.tgz?cache=0&sync_timestamp=1614705221099&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjquery%2Fdownload%2Fjquery-3.6.0.tgz",
+ "integrity": "sha1-xyoJ8Vwb3OFC9J2/EXC9+K2sJHA="
+ },
"js-stringify": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/js-stringify/download/js-stringify-1.0.2.tgz",
@@ -2575,6 +2635,11 @@
"integrity": "sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==",
"dev": true
},
+ "moment": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npm.taobao.org/moment/download/moment-2.20.1.tgz?cache=0&sync_timestamp=1601983320283&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmoment%2Fdownload%2Fmoment-2.20.1.tgz",
+ "integrity": "sha1-1usaRsvMFKKy+UNBEsH/iQfzE/0="
+ },
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.3.tgz?cache=0&sync_timestamp=1607433905701&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.3.tgz",
@@ -2680,6 +2745,14 @@
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true
},
+ "numbro": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npm.taobao.org/numbro/download/numbro-2.3.2.tgz",
+ "integrity": "sha1-SWfGMbDqmbF91/iM3R6qSs5NSXE=",
+ "requires": {
+ "bignumber.js": "^8.1.1"
+ }
+ },
"object-assign": {
"version": "4.1.1",
"resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz",
@@ -2887,6 +2960,14 @@
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
},
+ "pikaday": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npm.taobao.org/pikaday/download/pikaday-1.5.1.tgz",
+ "integrity": "sha1-CkhUm8GhTqHQjEQHTXYbwvK/z9M=",
+ "requires": {
+ "moment": "2.x"
+ }
+ },
"pinkie": {
"version": "2.0.4",
"resolved": "http://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz",
@@ -3492,6 +3573,12 @@
}
}
},
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha1-ysLazIoepnX+qrrriugziYrkb1U=",
+ "dev": true
+ },
"registry-auth-token": {
"version": "4.2.1",
"resolved": "https://registry.npm.taobao.org/registry-auth-token/download/registry-auth-token-4.2.1.tgz",
@@ -3976,6 +4063,11 @@
"integrity": "sha1-uLY5zvrX0LsqvTfUM/+Ck++l9AY=",
"dev": true
},
+ "tslib": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-2.0.3.tgz?cache=0&sync_timestamp=1617647074515&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-2.0.3.tgz",
+ "integrity": "sha1-jgdBrEX8DCJuWKF7/D5kubxsphw="
+ },
"type-fest": {
"version": "0.3.1",
"resolved": "https://registry.nlark.com/type-fest/download/type-fest-0.3.1.tgz?cache=0&sync_timestamp=1621402383646&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftype-fest%2Fdownload%2Ftype-fest-0.3.1.tgz",
@@ -5031,6 +5123,14 @@
"requires": {
"camelcase": "^4.1.0"
}
+ },
+ "zrender": {
+ "version": "5.1.0",
+ "resolved": "https://registry.nlark.com/zrender/download/zrender-5.1.0.tgz",
+ "integrity": "sha1-tqhMOqfMxmQu4FGZAcpMCDXE2F4=",
+ "requires": {
+ "tslib": "2.0.3"
+ }
}
}
}
diff --git a/package.json b/package.json
index cd90565..9d4a02a 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,9 @@
"serve": "vite preview"
},
"devDependencies": {
+ "@babel/polyfill": "^7.12.1",
"@tailwindcss/postcss7-compat": "^2.1.4",
+ "@types/jquery": "^3.5.5",
"@vitejs/plugin-vue": "^1.2.2",
"@vue/compiler-sfc": "^3.0.11",
"autoprefixer": "^9.8.6",
@@ -28,7 +30,10 @@
"yargs": "^6.6.0"
},
"dependencies": {
+ "echarts": "^5.1.1",
"element-plus": "^1.0.2-beta.44",
+ "handsontable": "^6.2.2",
+ "jquery": "^3.6.0",
"lodash": "^4.17.19",
"vue": "^3.0.11",
"vue-i18n": "^9.1.6"
diff --git a/src/components/BTable.vue b/src/components/BTable.vue
index ea64fd7..9f6fc36 100644
--- a/src/components/BTable.vue
+++ b/src/components/BTable.vue
@@ -1,34 +1,58 @@
<template>
<div class="w-full h-full">
- <div class="grid grid-cols-3 h-full">
- <div id="el-table" class="col-span-2 h-full" style="border: 1px solid red;"></div>
- <div id="el-config" class="p-3 align-middle">
- <div>
- <el-button type="button" onclick="run()" size="medium">运行</el-button>
- <el-button type="button" size="medium">导出</el-button>
+ <div class="grid grid-cols-12 h-full text-sm">
+ <el-card class="box-card col-span-3">
+ <h1 slot="header" class="clearfix text-xl">
+ Apache ECharts Bar-Race 生成器
+ </h1>
+ <div id="el-config" class="align-middle">
+ <!-- <div class="my-3">
+ <el-button onclick="run()" size="medium">运行</el-button>
+ <el-button size="medium">导出</el-button>
+ </div> -->
+ <el-form ref="form">
+ <div class="grid grid-cols-3 form-row">
+ <label class="col-span-1">标题</label>
+ <el-input id="input-title" value="汽车产量动态排名" size="medium" class="col-span-2"></el-input>
+ </div>
+ <div class="grid grid-cols-3 form-row">
+ <label class="col-span-1">显示排名上限</label>
+ <el-input id="input-max" type="number" value="10" size="medium" class="col-span-2"></el-input>
+ </div>
+ </el-form>
</div>
- <el-form ref="form">
- <div class="grid grid-cols-2 form-row">
- <label>标题</label>
- <el-input id="input-title" value="汽车产量动态排名" size="medium"></el-input>
- </div>
- <div class="grid grid-cols-2 form-row">
- <label>显示排名上限</label>
- <el-input id="input-max" type="number" value="10" size="medium"></el-input>
- </div>
- </el-form>
- </div>
+ </el-card>
+ <el-card class="box-card col-span-4 relative" body-style="height: 100%">
+ <div slot="header" class="clearfix text-base">
+ 数据
+ </div>
+ <div id="table-panel" class="overflow-auto absolute bottom-4 top-14 left-5 right-5 border">
+ </div>
+ </el-card>
+ <el-card class="box-card col-span-5 relative" body-style="height: 100%">
+ <div slot="header" class="clearfix text-base">
+ 预览
+ <a href="#">
+ <i class="el-icon-refresh"></i>
+ </a>
+ </div>
+ <div id="bar-race-preview" class="absolute bottom-4 top-14 left-5 right-5 border">
+ </div>
+ </el-card>
</div>
</div>
</template>
<script lang="ts">
-import {defineComponent} from 'vue'
+import {defineComponent} from 'vue';
+import btable from './btable';
+
export default defineComponent({
name: 'BTable',
props: {
},
- setup: () => {
+ mounted: () => {
+ btable.initTable();
}
})
</script>
@@ -42,5 +66,9 @@
@apply py-1;
}
}
+
+ .box-card {
+ @apply m-1;
+ }
}
</style>
diff --git a/src/components/btable.ts b/src/components/btable.ts
new file mode 100644
index 0000000..43eafec
--- /dev/null
+++ b/src/components/btable.ts
@@ -0,0 +1,243 @@
+import * as $ from 'jquery';
+import Handsontable from 'handsontable';
+import * as echarts from 'echarts';
+
+const headerLength = 2;
+
+let chart: echarts.ECharts;
+const data = [
+ ["Name", "Ford", "Tesla", "Toyota", "Honda"],
+ ["Color", "", "", "", ""],
+ ["2017", 10, 11, 12, 13],
+ ["2018", 20, 11, 14, 13],
+ ["2019", 30, 15, 12, 13]
+];
+
+function initTable() {
+ for (let i = 0; i < data.length; ++i) {
+ for (let j = data[i].length; j < 50; ++j) {
+ data[i].push('');
+ }
+ }
+ for (let i = data.length; i < 100; ++i) {
+ const row = [];
+ for (let j = 0; j < 50; ++j) {
+ row.push('');
+ }
+ data.push(row);
+ }
+
+ // function colorRenderer(instance, td, row, col) {
+ // //- console.log(instance);
+
+ // }
+
+ const container = document.getElementById('table-panel') as Element;
+ console.log(container)
+
+ const table = new Handsontable(container, {
+ data: data,
+ rowHeaders: true,
+ colHeaders: true,
+ filters: true,
+ dropdownMenu: true,
+ // cell: [{
+ // row: 0,
+ // col: 0,
+ // readOnly: true
+ // }, {
+ // row: 1,
+ // col: 0,
+ // readOnly: true
+ // }],
+ //- cells: function (row, col) {
+ //- if (row === 1) {
+ //- return {
+ //- renderer: colorRenderer
+ //- }
+ //- }
+ //- else {
+ //- return {};
+ //- }
+ //- }
+ });
+ table.updateSettings({
+ afterChange: function () {
+ run();
+ }
+ });
+
+ chart = echarts.init($('#bar-race-preview')[0]);
+ run();
+}
+
+const timeoutHandlers: number[] = [];
+
+function clearTimeoutHandlers() {
+ for (let i = 0; i < timeoutHandlers.length; ++i) {
+ clearTimeout(timeoutHandlers[i]);
+ timeoutHandlers.splice(i, 1);
+ }
+}
+function removeTimeoutHandlers(handler: number) {
+ for (let i = 0; i < timeoutHandlers.length; ++i) {
+ if (timeoutHandlers[i] === handler) {
+ timeoutHandlers.splice(i, 1);
+ }
+ }
+}
+
+function initEvents() {
+ $('.form-group').change(function () {
+ run();
+ });
+}
+
+
+function run() {
+ clearTimeoutHandlers();
+
+ const title = $('#input-title').val();
+ const max = $('#input-max').val();
+ chart.setOption({
+ title: [{
+ text: getDataName(0),
+ textStyle: {
+ fontFamily: 'monospace',
+ fontSize: 80,
+ color: 'rgba(100, 100, 100, 0.2)'
+ },
+ bottom: 60,
+ right: 20
+ }, {
+ text: title
+ }],
+ grid: {
+ right: 20
+ },
+ yAxis: {
+ type: 'category',
+ data: getYData(),
+ inverse: true,
+ max: max,
+ animationDuration: 0,
+ animationDurationUpdate: 0
+ },
+ xAxis: {},
+ series: [{
+ type: 'bar',
+ data: getChartData(0),
+ realtimeSort: true,
+ colorBy: 'item',
+ label: {
+ show: true,
+ position: 'insideRight'
+ }
+ }],
+ animationDurationUpdate: 5000,
+ animationEasing: 'linear',
+ animationEasingUpdate: 'linear'
+ }, true);
+
+ const rows = trimRows();
+ for (let i = 1; i < rows.length; ++i) {
+ (function (i) {
+ var dataRow = getChartData(i);
+ let timeout: number;
+ const timeoutCb = function () {
+ chart.setOption({
+ title: [{
+ text: getDataName(i)
+ }],
+ yAxis: {
+ animationDuration: 300,
+ animationDurationUpdate: 300,
+ },
+ series: [{
+ type: 'bar',
+ data: dataRow
+ }]
+ });
+ removeTimeoutHandlers(timeout);
+ };
+ timeout = window.setTimeout(timeoutCb, (i - 1) * 5000);
+ timeoutHandlers.push(timeout);
+ })(i);
+ }
+}
+
+const trimColumns = function (rowData: (string | number)[]) {
+ for (let i = rowData.length - 1; i > 0; --i) {
+ if (rowData[i] && rowData[i] !== '') {
+ return rowData.slice(1, i + 1);
+ }
+ }
+ return [];
+};
+
+const trimRows = function () {
+ if (data.length <= headerLength) {
+ return [];
+ }
+ for (let i = data.length - 1; i >= headerLength; --i) {
+ let isEmpty = true;
+ for (let j = 1; j < data[i].length; ++j) {
+ if (data[i][j] && data[i][j] !== '') {
+ isEmpty = false;
+ break;
+ }
+ }
+ if (!isEmpty) {
+ return data.slice(headerLength, i + 1);
+ }
+ }
+ return [];
+};
+
+const getYData = function () {
+ if (data.length <= headerLength) {
+ return [];
+ }
+ return trimColumns(data[0]);
+};
+
+const getChartData = function (id: number) {
+ if (data.length <= id + headerLength) {
+ return [];
+ }
+ return trimColumns(data[id + headerLength]);
+};
+
+const getDataName = function (id: number) {
+ if (data.length <= id + headerLength) {
+ return '';
+ }
+ else {
+ return data[id + headerLength][0];
+ }
+}
+
+function download() {
+ // saveFile()
+}
+
+function saveFile(name: string, type: string) {
+ // if (isSafari()) {
+ // window.open('data:text/plain;charset=utf-8,' + encodeURIComponent(data));
+ // } else {
+ // try {
+ // var file = new Blob([data], {type: type});
+ // saveAs(file, name);
+ // } catch(e) {
+ // console.error(e);
+ // window.open('data:text/plain;charset=utf-8,' + encodeURIComponent(data));
+ // }
+ // }
+}
+
+function isSafari() {
+ return navigator.userAgent.indexOf('Safari') > 0 &&
+ navigator.userAgent.indexOf('Chrome') < 0;
+}
+
+export default {initTable};
diff --git a/tsconfig.json b/tsconfig.json
index 5f1b278..6823c9a 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -11,5 +11,7 @@
"allowJs": true,
},
"include": ["src/**/*"],
- "exclude": ["node_modules"]
+ "exclude": ["node_modules"],
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true
}
\ No newline at end of file