{{ message }},{{ $t('chart.chart_show_error') }}
@@ -19,15 +20,18 @@ import { viewData } from '@/api/panel/panel'
import ChartComponent from '@/views/chart/components/ChartComponent.vue'
import TableNormal from '@/views/chart/components/table/TableNormal'
import LabelNormal from '../../../views/chart/components/normal/LabelNormal'
+import UserViewDialog from './UserViewDialog'
import { uuid } from 'vue-uuid'
import { mapState } from 'vuex'
import { isChange } from '@/utils/conditionUtil'
import { BASE_CHART_STRING } from '@/views/chart/chart/chart'
+import eventBus from '@/components/canvas/utils/eventBus'
+import { deepCopy } from '@/components/canvas/utils/utils'
export default {
name: 'UserView',
- components: { ChartComponent, TableNormal, LabelNormal },
+ components: { ChartComponent, TableNormal, LabelNormal, UserViewDialog },
props: {
element: {
type: Object,
@@ -170,6 +174,19 @@ export default {
},
viewIdMatch(viewIds, viewId) {
return !viewIds || viewIds.length === 0 || viewIds.includes(viewId)
+ },
+ openChartDetailsDialog() {
+ const tableChart = deepCopy(this.chart)
+ tableChart.customAttr = JSON.parse(this.chart.customAttr)
+ tableChart.customStyle = JSON.parse(this.chart.customStyle)
+ tableChart.customAttr.color.tableHeaderBgColor = '#f8f8f9'
+ tableChart.customAttr.color.tableItemBgColor = '#ffffff'
+ tableChart.customAttr.color.tableFontColor = '#7c7e81'
+ tableChart.customAttr.color.tableStripe = true
+ tableChart.customStyle.text.show = false
+ tableChart.customAttr = JSON.stringify(tableChart.customAttr)
+ tableChart.customStyle = JSON.stringify(tableChart.customStyle)
+ eventBus.$emit('openChartDetailsDialog', { chart: this.chart, tableChart: tableChart })
}
}
}
@@ -195,4 +212,24 @@ export default {
justify-content: center;
background-color: #ece7e7;
}
+
+.rect-shape > i{
+ right: 5px;
+ color: gray;
+ position: absolute;
+}
+
+.rect-shape > i:hover {
+ color: red;
+}
+
+.rect-shape:hover > .icon-quanping1 {
+ z-index: 2;
+ display:block;
+}
+
+.rect-shape>>>.icon-quanping1 {
+ display:none
+}
+
diff --git a/frontend/src/components/canvas/custom-component/UserViewDialog.vue b/frontend/src/components/canvas/custom-component/UserViewDialog.vue
new file mode 100644
index 0000000000..362a66f215
--- /dev/null
+++ b/frontend/src/components/canvas/custom-component/UserViewDialog.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js
index 4783ca7973..f5f724d3f0 100644
--- a/frontend/src/lang/en.js
+++ b/frontend/src/lang/en.js
@@ -796,6 +796,9 @@ export default {
filter_value_can_null: 'Filter value can not empty',
filter_like: 'Contain',
filter_not_like: 'Not Contain',
+ chart_details: 'Chart Details',
+ export_details: 'Export Details'
+ filter_not_like: 'Not Contain',
color_light: 'Light',
color_classical: 'Classical',
color_fresh: 'Fresh',
diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js
index 3953fa9032..256dec5dd2 100644
--- a/frontend/src/lang/tw.js
+++ b/frontend/src/lang/tw.js
@@ -803,6 +803,9 @@ export default {
color_red: '火紅',
color_fast: '輕快',
color_spiritual: '靈動'
+ filter_not_like: '不包含',
+ chart_details: '视图明细',
+ export_details: '导出明细'
},
dataset: {
sheet_warn: '有多個sheet頁面,默認抽取第一個',
diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js
index 33c6f372d0..b004692e99 100644
--- a/frontend/src/lang/zh.js
+++ b/frontend/src/lang/zh.js
@@ -803,6 +803,9 @@ export default {
color_red: '火红',
color_fast: '轻快',
color_spiritual: '灵动'
+ filter_not_like: '不包含',
+ chart_details: '视图明细',
+ export_details: '导出明细'
},
dataset: {
sheet_warn: '有多个 Sheet 页,默认抽取第一个',
diff --git a/frontend/src/plugins/Blob.js b/frontend/src/plugins/Blob.js
new file mode 100644
index 0000000000..5ffc1337fd
--- /dev/null
+++ b/frontend/src/plugins/Blob.js
@@ -0,0 +1,210 @@
+/* eslint-disable */
+/* Blob.js*/
+
+/*global self, unescape */
+/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
+ plusplus: true */
+
+/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
+
+(function (view) {
+ "use strict";
+
+ view.URL = view.URL || view.webkitURL;
+
+ if (view.Blob && view.URL) {
+ try {
+ new Blob;
+ return;
+ } catch (e) {
+ }
+ }
+
+ // Internally we use a BlobBuilder implementation to base Blob off of
+ // in order to support older browsers that only have BlobBuilder
+ var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function (view) {
+ var
+ get_class = function (object) {
+ return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
+ }
+ , FakeBlobBuilder = function BlobBuilder() {
+ this.data = [];
+ }
+ , FakeBlob = function Blob(data, type, encoding) {
+ this.data = data;
+ this.size = data.length;
+ this.type = type;
+ this.encoding = encoding;
+ }
+ , FBB_proto = FakeBlobBuilder.prototype
+ , FB_proto = FakeBlob.prototype
+ , FileReaderSync = view.FileReaderSync
+ , FileException = function (type) {
+ this.code = this[this.name = type];
+ }
+ , file_ex_codes = (
+ "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
+ + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
+ ).split(" ")
+ , file_ex_code = file_ex_codes.length
+ , real_URL = view.URL || view.webkitURL || view
+ , real_create_object_URL = real_URL.createObjectURL
+ , real_revoke_object_URL = real_URL.revokeObjectURL
+ , URL = real_URL
+ , btoa = view.btoa
+ , atob = view.atob
+
+ , ArrayBuffer = view.ArrayBuffer
+ , Uint8Array = view.Uint8Array
+
+ , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
+ ;
+ FakeBlob.fake = FB_proto.fake = true;
+ while (file_ex_code--) {
+ FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
+ }
+ // Polyfill URL
+ if (!real_URL.createObjectURL) {
+ URL = view.URL = function (uri) {
+ var
+ uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
+ , uri_origin
+ ;
+ uri_info.href = uri;
+ if (!("origin" in uri_info)) {
+ if (uri_info.protocol.toLowerCase() === "data:") {
+ uri_info.origin = null;
+ } else {
+ uri_origin = uri.match(origin);
+ uri_info.origin = uri_origin && uri_origin[1];
+ }
+ }
+ return uri_info;
+ };
+ }
+ URL.createObjectURL = function (blob) {
+ var
+ type = blob.type
+ , data_URI_header
+ ;
+ if (type === null) {
+ type = "application/octet-stream";
+ }
+ if (blob instanceof FakeBlob) {
+ data_URI_header = "data:" + type;
+ if (blob.encoding === "base64") {
+ return data_URI_header + ";base64," + blob.data;
+ } else if (blob.encoding === "URI") {
+ return data_URI_header + "," + decodeURIComponent(blob.data);
+ }
+ if (btoa) {
+ return data_URI_header + ";base64," + btoa(blob.data);
+ } else {
+ return data_URI_header + "," + encodeURIComponent(blob.data);
+ }
+ } else if (real_create_object_URL) {
+ return real_create_object_URL.call(real_URL, blob);
+ }
+ };
+ URL.revokeObjectURL = function (object_URL) {
+ if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
+ real_revoke_object_URL.call(real_URL, object_URL);
+ }
+ };
+ FBB_proto.append = function (data/*, endings*/) {
+ var bb = this.data;
+ // decode data to a binary string
+ if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
+ var
+ str = ""
+ , buf = new Uint8Array(data)
+ , i = 0
+ , buf_len = buf.length
+ ;
+ for (; i < buf_len; i++) {
+ str += String.fromCharCode(buf[i]);
+ }
+ bb.push(str);
+ } else if (get_class(data) === "Blob" || get_class(data) === "File") {
+ if (FileReaderSync) {
+ var fr = new FileReaderSync;
+ bb.push(fr.readAsBinaryString(data));
+ } else {
+ // async FileReader won't work as BlobBuilder is sync
+ throw new FileException("NOT_READABLE_ERR");
+ }
+ } else if (data instanceof FakeBlob) {
+ if (data.encoding === "base64" && atob) {
+ bb.push(atob(data.data));
+ } else if (data.encoding === "URI") {
+ bb.push(decodeURIComponent(data.data));
+ } else if (data.encoding === "raw") {
+ bb.push(data.data);
+ }
+ } else {
+ if (typeof data !== "string") {
+ data += ""; // convert unsupported types to strings
+ }
+ // decode UTF-16 to binary string
+ bb.push(unescape(encodeURIComponent(data)));
+ }
+ };
+ FBB_proto.getBlob = function (type) {
+ if (!arguments.length) {
+ type = null;
+ }
+ return new FakeBlob(this.data.join(""), type, "raw");
+ };
+ FBB_proto.toString = function () {
+ return "[object BlobBuilder]";
+ };
+ FB_proto.slice = function (start, end, type) {
+ var args = arguments.length;
+ if (args < 3) {
+ type = null;
+ }
+ return new FakeBlob(
+ this.data.slice(start, args > 1 ? end : this.data.length)
+ , type
+ , this.encoding
+ );
+ };
+ FB_proto.toString = function () {
+ return "[object Blob]";
+ };
+ FB_proto.close = function () {
+ this.size = 0;
+ delete this.data;
+ };
+ return FakeBlobBuilder;
+ }(view));
+
+ view.Blob = function (blobParts, options) {
+ var type = options ? (options.type || "") : "";
+ var builder = new BlobBuilder();
+ if (blobParts) {
+ for (var i = 0, len = blobParts.length; i < len; i++) {
+ if (Uint8Array && blobParts[i] instanceof Uint8Array) {
+ builder.append(blobParts[i].buffer);
+ }
+ else {
+ builder.append(blobParts[i]);
+ }
+ }
+ }
+ var blob = builder.getBlob(type);
+ if (!blob.slice && blob.webkitSlice) {
+ blob.slice = blob.webkitSlice;
+ }
+ return blob;
+ };
+
+ var getPrototypeOf = Object.getPrototypeOf || function (object) {
+ return object.__proto__;
+ };
+ view.Blob.prototype = getPrototypeOf(new view.Blob());
+ }(
+ typeof self !== "undefined" && self
+ || typeof window !== "undefined" && window
+ || this
+ ));
\ No newline at end of file
diff --git a/frontend/src/plugins/Export2Excel.js b/frontend/src/plugins/Export2Excel.js
new file mode 100644
index 0000000000..7252b86318
--- /dev/null
+++ b/frontend/src/plugins/Export2Excel.js
@@ -0,0 +1,184 @@
+require('script-loader!file-saver')
+/* 这里的路径换成自己的 */
+require('@/plugins/Blob.js')
+require('script-loader!xlsx/dist/xlsx.core.min')
+
+function generateArray(table) {
+ var out = []
+ var rows = table.querySelectorAll('tr')
+ var ranges = []
+ for (var R = 0; R < rows.length; ++R) {
+ var outRow = []
+ var row = rows[R]
+ var columns = row.querySelectorAll('td')
+ for (var C = 0; C < columns.length; ++C) {
+ var cell = columns[C]
+ var colspan = cell.getAttribute('colspan')
+ var rowspan = cell.getAttribute('rowspan')
+ var cellValue = cell.innerText
+ if (cellValue !== '' && cellValue == +cellValue) cellValue = +cellValue
+
+ // Skip ranges
+ ranges.forEach(function(range) {
+ if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
+ for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null)
+ }
+ })
+
+ // Handle Row Span
+ if (rowspan || colspan) {
+ rowspan = rowspan || 1
+ colspan = colspan || 1
+ ranges.push({ s: { r: R, c: outRow.length }, e: { r: R + rowspan - 1, c: outRow.length + colspan - 1 }})
+ }
+
+ // Handle Value
+ outRow.push(cellValue !== '' ? cellValue : null)
+
+ // Handle Colspan
+ if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null)
+ }
+ out.push(outRow)
+ }
+ return [out, ranges]
+}
+
+function datenum(v, date1904) {
+ if (date1904) v += 1462
+ var epoch = Date.parse(v)
+ return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000)
+}
+
+function sheet_from_array_of_arrays(data, opts) {
+ var ws = {}
+ var range = { s: { c: 10000000, r: 10000000 }, e: { c: 0, r: 0 }}
+ for (var R = 0; R != data.length; ++R) {
+ for (var C = 0; C != data[R].length; ++C) {
+ if (range.s.r > R) range.s.r = R
+ if (range.s.c > C) range.s.c = C
+ if (range.e.r < R) range.e.r = R
+ if (range.e.c < C) range.e.c = C
+ var cell = { v: data[R][C] }
+ if (cell.v == null) continue
+ var cell_ref = XLSX.utils.encode_cell({ c: C, r: R })
+
+ if (typeof cell.v === 'number') cell.t = 'n'
+ else if (typeof cell.v === 'boolean') cell.t = 'b'
+ else if (cell.v instanceof Date) {
+ cell.t = 'n'
+ cell.z = XLSX.SSF._table[14]
+ cell.v = datenum(cell.v)
+ } else cell.t = 's'
+
+ ws[cell_ref] = cell
+ }
+ }
+ if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range)
+ return ws
+}
+
+function Workbook() {
+ if (!(this instanceof Workbook)) return new Workbook()
+ this.SheetNames = []
+ this.Sheets = {}
+}
+
+function s2ab(s) {
+ var buf = new ArrayBuffer(s.length)
+ var view = new Uint8Array(buf)
+ for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
+ return buf
+}
+
+export function export_table_to_excel(id) {
+ var theTable = document.getElementById(id)
+ console.log('a')
+ var oo = generateArray(theTable)
+ var ranges = oo[1]
+
+ /* original data */
+ var data = oo[0]
+ var ws_name = 'SheetJS'
+ console.log(data)
+
+ var wb = new Workbook(); var ws = sheet_from_array_of_arrays(data)
+
+ /* add ranges to worksheet */
+ // ws['!cols'] = ['apple', 'banan'];
+ ws['!merges'] = ranges
+
+ /* add worksheet to workbook */
+ wb.SheetNames.push(ws_name)
+ wb.Sheets[ws_name] = ws
+
+ var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' })
+
+ saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), 'test.xlsx')
+}
+
+function formatJson(jsonData) {
+ console.log(jsonData)
+}
+
+export function export_json_to_excel(th, jsonData, defaultTitle) {
+ /* original data */
+
+ var data = jsonData
+ data.unshift(th)
+ var ws_name = 'SheetJS'
+
+ var wb = new Workbook(); var ws = sheet_from_array_of_arrays(data)
+
+ /* add worksheet to workbook */
+ wb.SheetNames.push(ws_name)
+ wb.Sheets[ws_name] = ws
+
+ var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' })
+ var title = defaultTitle || '列表'
+ saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), title + '.xlsx')
+}
+// export default{
+// export_json_to_excel(th, jsonData, defaultTitle) {
+
+// /* original data */
+
+// var data = jsonData;
+// data.unshift(th);
+// var ws_name = "SheetJS";
+
+// var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
+
+// /* add worksheet to workbook */
+// wb.SheetNames.push(ws_name);
+// wb.Sheets[ws_name] = ws;
+
+// var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'});
+// var title = defaultTitle || '列表'
+// saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx")
+// },
+// export_table_to_excel(id) {
+// var theTable = document.getElementById(id);
+// console.log('a')
+// var oo = generateArray(theTable);
+// var ranges = oo[1];
+
+// /* original data */
+// var data = oo[0];
+// var ws_name = "SheetJS";
+// console.log(data);
+
+// var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
+
+// /* add ranges to worksheet */
+// // ws['!cols'] = ['apple', 'banan'];
+// ws['!merges'] = ranges;
+
+// /* add worksheet to workbook */
+// wb.SheetNames.push(ws_name);
+// wb.Sheets[ws_name] = ws;
+
+// var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'});
+
+// saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx")
+// }
+// }
diff --git a/frontend/src/styles/deicon/demo_index.html b/frontend/src/styles/deicon/demo_index.html
index 4adafd5a93..710b54b0fc 100644
--- a/frontend/src/styles/deicon/demo_index.html
+++ b/frontend/src/styles/deicon/demo_index.html
@@ -54,6 +54,12 @@
+ -
+
+
屏幕_全屏
+ 
+
+
-
font-weight-bold
@@ -264,9 +270,9 @@
@font-face {
font-family: 'iconfont';
- src: url('iconfont.woff2?t=1625198204132') format('woff2'),
- url('iconfont.woff?t=1625198204132') format('woff'),
- url('iconfont.ttf?t=1625198204132') format('truetype');
+ src: url('iconfont.woff2?t=1625729811345') format('woff2'),
+ url('iconfont.woff?t=1625729811345') format('woff'),
+ url('iconfont.ttf?t=1625729811345') format('truetype');
}
第二步:定义使用 iconfont 的样式
@@ -292,6 +298,15 @@
+ -
+
+
+ 屏幕_全屏
+
+ .icon-quanping1
+
+
+
-
@@ -607,6 +622,14 @@
+ -
+
+
屏幕_全屏
+ #icon-quanping1
+
+
-