From f2e1f450efe602fb417087d36bfb81596c5c5823 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 31 May 2023 15:36:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B5=8B=E8=AF=95=E6=8A=A5=E8=A1=A8?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 10 +- src/api/model/bi.js | 92 +++++++++ src/api/model/em.js | 76 +++++++ src/config/route.js | 74 +++++++ src/main.js | 6 +- src/utils/print2.js | 171 ++++++++++++++++ src/utils/xlsx.js | 11 + src/views/bi/dataset.vue | 230 +++++++++++++++++++++ src/views/bi/dataset_form.vue | 162 +++++++++++++++ src/views/bi/graph.vue | 349 ++++++++++++++++++++++++++++++++ src/views/bi/report.vue | 190 +++++++++++++++++ src/views/bi/report_form.vue | 159 +++++++++++++++ src/views/em/equipment.vue | 171 ++++++++++++++++ src/views/em/equipment_form.vue | 200 ++++++++++++++++++ 14 files changed, 1895 insertions(+), 6 deletions(-) create mode 100644 src/api/model/bi.js create mode 100644 src/api/model/em.js create mode 100644 src/utils/print2.js create mode 100644 src/utils/xlsx.js create mode 100644 src/views/bi/dataset.vue create mode 100644 src/views/bi/dataset_form.vue create mode 100644 src/views/bi/graph.vue create mode 100644 src/views/bi/report.vue create mode 100644 src/views/bi/report_form.vue create mode 100644 src/views/em/equipment.vue create mode 100644 src/views/em/equipment_form.vue diff --git a/package.json b/package.json index f3a41c6e..d01fcfd7 100644 --- a/package.json +++ b/package.json @@ -19,15 +19,14 @@ "d3": "^7.6.1", "dagre": "^0.8.5", "dagre-d3": "^0.6.4", - "echarts": "5.3.2", - "element-plus": "2.2.3", - "html2canvas": "^1.4.1", - "json-editor-vue3": "^1.0.6", - "xlsx": "^0.18.5", "echarts": "5.4.1", "element-plus": "2.2.32", + "file-saver": "^2.0.5", + "html2canvas": "^1.4.1", + "json-editor-vue3": "^1.0.6", "jspdf": "^2.5.1", "nprogress": "0.2.0", + "print-js": "^1.6.0", "qrcodejs2": "0.0.2", "sortablejs": "1.15.0", "tinymce": "6.3.2", @@ -38,6 +37,7 @@ "vuex": "4.1.0", "xgplayer": "2.32.2", "xgplayer-hls": "2.5.2", + "xlsx": "^0.18.5", "xlsx-style": "^0.8.13" }, "devDependencies": { diff --git a/src/api/model/bi.js b/src/api/model/bi.js new file mode 100644 index 00000000..fb928673 --- /dev/null +++ b/src/api/model/bi.js @@ -0,0 +1,92 @@ +import config from "@/config" +import http from "@/utils/request" +/*BI接口*/ +export default { + + dataset: { + list: { + name: "获取数据集列表", + req: async function(data){ + return await http.get( + `${config.API_URL}/bi/dataset/`, + data + ); + } + }, + item: { + name: "获取某个数据集详情", + req: async function(id){ + return await http.get( + `${config.API_URL}/bi/dataset/${id}/` + ); + } + }, + update: { + name: "更新数据集", + req: async function(id, data){ + return await http.put( + `${config.API_URL}/bi/dataset/${id}/`, + data); + } + }, + create: { + name: "创建数据集", + req: async function(data){ + return await http.post( + `${config.API_URL}/bi/dataset/`, + data); + } + }, + exec: { + name: "执行", + req: async function(id, data){ + return await http.post( + `${config.API_URL}/bi/dataset/${id}/exec/`, + data); + } + }, + }, + report: { + list: { + name: "获取列表", + req: async function(data){ + return await http.get( + `${config.API_URL}/bi/report/`, + data + ); + } + }, + item: { + name: "获取详情", + req: async function(id){ + return await http.get( + `${config.API_URL}/bi/report/${id}/` + ); + } + }, + update: { + name: "更新", + req: async function(id, data){ + return await http.put( + `${config.API_URL}/bi/report/${id}/`, + data); + } + }, + create: { + name: "创建", + req: async function(data){ + return await http.post( + `${config.API_URL}/bi/report/`, + data); + } + }, + exec: { + name: "执行", + req: async function(id, data){ + return await http.post( + `${config.API_URL}/bi/report/${id}/exec/`, + data); + } + }, + }, +} \ No newline at end of file diff --git a/src/api/model/em.js b/src/api/model/em.js new file mode 100644 index 00000000..ceac5338 --- /dev/null +++ b/src/api/model/em.js @@ -0,0 +1,76 @@ +import config from "@/config" +import http from "@/utils/request" +/*EM接口*/ +export default { + + equipment: { + list: { + name: "获取列表", + req: async function(data){ + return await http.get( + `${config.API_URL}/em/equipment/`, + data + ); + } + }, + item: { + name: "获取详情", + req: async function(id){ + return await http.get( + `${config.API_URL}/em/equipment/${id}/` + ); + } + }, + update: { + name: "更新", + req: async function(id, data){ + return await http.put( + `${config.API_URL}/em/equipment/${id}/`, + data); + } + }, + create: { + name: "创建", + req: async function(data){ + return await http.post( + `${config.API_URL}/em/equipment/`, + data); + } + } + }, + mpoint: { + list: { + name: "获取列表", + req: async function(data){ + return await http.get( + `${config.API_URL}/em/mpoint/`, + data + ); + } + }, + item: { + name: "获取详情", + req: async function(id){ + return await http.get( + `${config.API_URL}/em/mpoint/${id}/` + ); + } + }, + update: { + name: "更新", + req: async function(id, data){ + return await http.put( + `${config.API_URL}/em/mpoint/${id}/`, + data); + } + }, + create: { + name: "创建", + req: async function(data){ + return await http.post( + `${config.API_URL}/em/mpoint/`, + data); + } + } + }, +} \ No newline at end of file diff --git a/src/config/route.js b/src/config/route.js index e5209c62..91e6486b 100644 --- a/src/config/route.js +++ b/src/config/route.js @@ -93,9 +93,83 @@ const routes = [ "perms": ["userCenter"] }, "component": "userCenter" + }, + ] + }, + { + "name": "bi", + "path": "/bi", + "meta": { + "title": "报表", + "icon": "el-icon-grid", + "type": "menu", + "perms": ["bi"] + }, + "children": [ + { + "name": "dataset", + "path": "/bi/dataset", + "meta": { + "title": "数据集", + "icon": "el-icon-grid", + "perms": ["dataset"] + }, + "component": "bi/dataset" + }, + { + "name": "graph", + "path": "/bi/graph", + "meta": { + "title": "测试图", + "icon": "el-icon-grid", + "perms": ["dataset"] + }, + "component": "bi/graph" } ] }, + { + "name": "em", + "path": "/em", + "meta": { + "title": "设备", + "icon": "el-icon-grid", + "type": "menu", + "perms": ["em"] + }, + "children": [ + { + "name": "equipment", + "path": "/em/equipment", + "meta": { + "title": "生产设备", + "icon": "el-icon-grid", + "perms": ["equipment"] + }, + "component": "em/equipment" + }, + { + "name": "equipment2", + "path": "/em/equipment2", + "meta": { + "title": "计量设备", + "icon": "el-icon-grid", + "perms": ["equipment"] + }, + "component": "em/equipment" + }, + { + "name": "em", + "path": "/em/mpoint", + "meta": { + "title": "测点管理", + "icon": "el-icon-grid", + "perms": ["mpoint"] + }, + "component": "em/equipment" + }, + ] + }, { "name": "ecm", "path": "/ecm", diff --git a/src/main.js b/src/main.js index c1d96c70..b75eb2c9 100644 --- a/src/main.js +++ b/src/main.js @@ -10,6 +10,8 @@ import store from './store' import App from './App.vue' import * as ElementPlusIconsVue from '@element-plus/icons-vue' import preventReClick from './utils/preventReClick' +import Print from './utils/print2' +import Xlsx from './utils/xlsx' const app = createApp(App); @@ -19,7 +21,9 @@ app.use(ElementPlus); app.use(i18n); app.use(scui); app.use(ehsui); -app.use(preventReClick) +app.use(preventReClick); +app.use(Print); +app.use(Xlsx); //挂载app app.mount('#app'); for (const [key, component] of Object.entries(ElementPlusIconsVue)) { diff --git a/src/utils/print2.js b/src/utils/print2.js new file mode 100644 index 00000000..99bc0198 --- /dev/null +++ b/src/utils/print2.js @@ -0,0 +1,171 @@ +// 打印类属性、方法定义 +/* eslint-disable */ +const Print = function (dom, options) { + if (!(this instanceof Print)) return new Print(dom, options); + + this.options = this.extend({ + 'noPrint': '.no-print' + }, options); + + if ((typeof dom) === "string") { + this.dom = document.querySelector(dom); + } else { + this.isDOM(dom) + this.dom = this.isDOM(dom) ? dom : dom.$el; + } + + this.init(); + }; + Print.prototype = { + init: function () { + var content = this.getStyle() + this.getHtml(); + this.writeIframe(content); + }, + extend: function (obj, obj2) { + for (var k in obj2) { + obj[k] = obj2[k]; + } + return obj; + }, + + getStyle: function () { + var str = "", + styles = document.querySelectorAll('style,link'); + for (var i = 0; i < styles.length; i++) { + str += styles[i].outerHTML; + } + str += ""; + // 去除height:100%样式,解决分页下,样式混乱问题 + str += ""; + + return str; + }, + + getHtml: function () { + var inputs = document.querySelectorAll('input'); + var textareas = document.querySelectorAll('textarea'); + var selects = document.querySelectorAll('select'); + var canvass = document.querySelectorAll('canvas'); + + for (var k = 0; k < inputs.length; k++) { + if (inputs[k].type == "checkbox" || inputs[k].type == "radio") { + if (inputs[k].checked == true) { + inputs[k].setAttribute('checked', "checked") + } else { + inputs[k].removeAttribute('checked') + } + } else if (inputs[k].type == "text") { + inputs[k].setAttribute('value', inputs[k].value) + } else { + inputs[k].setAttribute('value', inputs[k].value) + } + } + + for (var k2 = 0; k2 < textareas.length; k2++) { + if (textareas[k2].type == 'textarea') { + textareas[k2].innerHTML = textareas[k2].value + } + } + + for (var k3 = 0; k3 < selects.length; k3++) { + if (selects[k3].type == 'select-one') { + var child = selects[k3].children; + for (var i in child) { + if (child[i].tagName == 'OPTION') { + if (child[i].selected == true) { + child[i].setAttribute('selected', "selected") + } else { + child[i].removeAttribute('selected') + } + } + } + } + } + + //canvass echars图表转为图片 + for (var k4 = 0; k4 < canvass.length; k4++) { + var imageURL = canvass[k4].toDataURL("image/png"); + var img = document.createElement("img"); + img.src = imageURL; + img.setAttribute('style', 'max-width: 100%;'); + img.className = 'isNeedRemove' + // canvass[k4].style.display = 'none' + // canvass[k4].parentNode.style.width = '100%' + // canvass[k4].parentNode.style.textAlign = 'center' + canvass[k4].parentNode.insertBefore(img,canvass[k4].nextElementSibling); + } + + // 包裹要打印的元素 + // fix: https://github.com/xyl66/vuePlugs_printjs/issues/36 + // return this.wrapperRefDom(this.dom).outerHTML; + return this.dom.outerHTML; + }, + // 向父级元素循环,包裹当前需要打印的元素 + // 防止根级别开头的 css 选择器不生效 + wrapperRefDom: function (refDom) { + let prevDom = null + let currDom = refDom + while (currDom && currDom.tagName.toLowerCase() !== 'body') { + if (prevDom) { + let element = currDom.cloneNode(false) + element.appendChild(prevDom) + prevDom = element + } else { + prevDom = currDom.cloneNode(true) + } + + currDom = currDom.parentElement + } + + return currDom.tagName.toLowerCase() === 'body' ? currDom : prevDom + }, + + writeIframe: function (content) { + var w, doc, iframe = document.createElement('iframe'), + f = document.body.appendChild(iframe); + iframe.id = "myIframe"; + //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;"; + iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;'); + w = f.contentWindow || f.contentDocument; + doc = f.contentDocument || f.contentWindow.document; + doc.open(); + doc.write(content); + doc.close(); + var _this = this + iframe.onload = function(){ + _this.toPrint(w); + setTimeout(function () { + document.body.removeChild(iframe) + }, 100) + } + }, + + toPrint: function (frameWindow) { + try { + setTimeout(function () { + frameWindow.focus(); + try { + if (!frameWindow.document.execCommand('print', false, null)) { + frameWindow.print(); + } + } catch (e) { + frameWindow.print(); + } + frameWindow.close(); + }, 10); + } catch (err) { + console.log('err', err); + } + }, + isDOM: (typeof HTMLElement === 'object') ? + function (obj) { + return obj instanceof HTMLElement; + } : + function (obj) { + return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string'; + } + }; + export default (app) => { + app.config.globalProperties.$PRINT = Print; +} + \ No newline at end of file diff --git a/src/utils/xlsx.js b/src/utils/xlsx.js new file mode 100644 index 00000000..151c8567 --- /dev/null +++ b/src/utils/xlsx.js @@ -0,0 +1,11 @@ +import * as XLSX from "xlsx"; + +const ExportExcel = function(domId, name) { + const table = document.querySelector(domId); + const workbook = XLSX.utils.table_to_book(table); + + XLSX.writeFile(workbook, `${name}.xlsx`); +} +export default (app) => { + app.config.globalProperties.$XLSX = ExportExcel; +} \ No newline at end of file diff --git a/src/views/bi/dataset.vue b/src/views/bi/dataset.vue new file mode 100644 index 00000000..d93dd461 --- /dev/null +++ b/src/views/bi/dataset.vue @@ -0,0 +1,230 @@ + + \ No newline at end of file diff --git a/src/views/bi/dataset_form.vue b/src/views/bi/dataset_form.vue new file mode 100644 index 00000000..b2e52700 --- /dev/null +++ b/src/views/bi/dataset_form.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/src/views/bi/graph.vue b/src/views/bi/graph.vue new file mode 100644 index 00000000..8ccf25b3 --- /dev/null +++ b/src/views/bi/graph.vue @@ -0,0 +1,349 @@ + + + \ No newline at end of file diff --git a/src/views/bi/report.vue b/src/views/bi/report.vue new file mode 100644 index 00000000..cc3209a3 --- /dev/null +++ b/src/views/bi/report.vue @@ -0,0 +1,190 @@ + + \ No newline at end of file diff --git a/src/views/bi/report_form.vue b/src/views/bi/report_form.vue new file mode 100644 index 00000000..fafdb768 --- /dev/null +++ b/src/views/bi/report_form.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/src/views/em/equipment.vue b/src/views/em/equipment.vue new file mode 100644 index 00000000..15ee414e --- /dev/null +++ b/src/views/em/equipment.vue @@ -0,0 +1,171 @@ + + \ No newline at end of file diff --git a/src/views/em/equipment_form.vue b/src/views/em/equipment_form.vue new file mode 100644 index 00000000..dee792e0 --- /dev/null +++ b/src/views/em/equipment_form.vue @@ -0,0 +1,200 @@ + + + + +