From e8b4c98c16b6721a7d6617aecf82bfbc23655a58 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期一, 21 十月 2024 11:23:09 +0800
Subject: [PATCH] 1. 数据产品模块(暂存)

---
 src/views/fysp/data-product/ProdSceneReport.vue                     |    3 
 src/api/fysp/dataproductApi.js                                      |   34 +++
 package-lock.json                                                   |  158 +++++++++++++++++
 src/api/index.js                                                    |    2 
 package.json                                                        |    3 
 src/components.d.ts                                                 |   11 +
 src/views/fysp/data-product/ProdProAnalysis.vue                     |   11 +
 src/views/fysp/data-product/ProdStandardJudge.vue                   |   11 +
 src/views/fysp/data-product/components/CompReportDownloadDialog.vue |   80 ++++++++
 src/components/core/SiderMenu.vue                                   |    6 
 src/views/fysp/data-product/ProdProFollow.vue                       |   11 +
 src/views/fysp/data-product/components/BaseDataProduct.vue          |  185 ++++++++++++++++++++
 12 files changed, 509 insertions(+), 6 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 508cba5..1f45c2b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,7 +20,8 @@
         "pinia": "^2.0.26",
         "vue": "^3.2.45",
         "vue-i18n": "^9.8.0",
-        "vue-router": "^4.1.6"
+        "vue-router": "^4.1.6",
+        "xlsx": "^0.18.5"
       },
       "devDependencies": {
         "@babel/cli": "^7.19.3",
@@ -2800,6 +2801,14 @@
         "node": ">=0.4.0"
       }
     },
+    "node_modules/adler-32": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz",
+      "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/agent-base": {
       "version": "6.0.2",
       "dev": true,
@@ -3294,6 +3303,18 @@
       "dev": true,
       "license": "Apache-2.0"
     },
+    "node_modules/cfb": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz",
+      "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
+      "dependencies": {
+        "adler-32": "~1.3.0",
+        "crc-32": "~1.2.0"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/chai": {
       "version": "4.3.7",
       "dev": true,
@@ -3463,6 +3484,14 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/codepage": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz",
+      "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/color-convert": {
       "version": "2.0.1",
       "dev": true,
@@ -3547,6 +3576,17 @@
       "version": "1.0.2",
       "dev": true,
       "license": "MIT"
+    },
+    "node_modules/crc-32": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz",
+      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+      "bin": {
+        "crc32": "bin/crc32.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
     },
     "node_modules/cross-spawn": {
       "version": "7.0.3",
@@ -4520,6 +4560,14 @@
       },
       "engines": {
         "node": ">= 0.12"
+      }
+    },
+    "node_modules/frac": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz",
+      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
+      "engines": {
+        "node": ">=0.8"
       }
     },
     "node_modules/fraction.js": {
@@ -6546,6 +6594,17 @@
         "node": "*"
       }
     },
+    "node_modules/ssf": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz",
+      "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
+      "dependencies": {
+        "frac": "~1.1.2"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/sshpk": {
       "version": "1.17.0",
       "dev": true,
@@ -7596,6 +7655,22 @@
         "node": ">= 8"
       }
     },
+    "node_modules/wmf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz",
+      "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/word": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/word/-/word-0.3.0.tgz",
+      "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/word-wrap": {
       "version": "1.2.3",
       "dev": true,
@@ -7643,6 +7718,26 @@
         "utf-8-validate": {
           "optional": true
         }
+      }
+    },
+    "node_modules/xlsx": {
+      "version": "0.18.5",
+      "resolved": "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz",
+      "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
+      "dependencies": {
+        "adler-32": "~1.3.0",
+        "cfb": "~1.2.1",
+        "codepage": "~1.15.0",
+        "crc-32": "~1.2.1",
+        "ssf": "~0.11.2",
+        "wmf": "~1.0.1",
+        "word": "~0.3.0"
+      },
+      "bin": {
+        "xlsx": "bin/xlsx.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
       }
     },
     "node_modules/xml-name-validator": {
@@ -9473,6 +9568,11 @@
       "version": "8.2.0",
       "dev": true
     },
+    "adler-32": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz",
+      "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A=="
+    },
     "agent-base": {
       "version": "6.0.2",
       "dev": true,
@@ -9751,6 +9851,15 @@
       "version": "0.12.0",
       "dev": true
     },
+    "cfb": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz",
+      "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
+      "requires": {
+        "adler-32": "~1.3.0",
+        "crc-32": "~1.2.0"
+      }
+    },
     "chai": {
       "version": "4.3.7",
       "dev": true,
@@ -9853,6 +9962,11 @@
         "string-width": "^4.2.0"
       }
     },
+    "codepage": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz",
+      "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
+    },
     "color-convert": {
       "version": "2.0.1",
       "dev": true,
@@ -9907,6 +10021,11 @@
     "core-util-is": {
       "version": "1.0.2",
       "dev": true
+    },
+    "crc-32": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz",
+      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
     },
     "cross-spawn": {
       "version": "7.0.3",
@@ -10554,6 +10673,11 @@
         "combined-stream": "^1.0.6",
         "mime-types": "^2.1.12"
       }
+    },
+    "frac": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz",
+      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
     },
     "fraction.js": {
       "version": "4.2.0",
@@ -11781,6 +11905,14 @@
         "through": "2"
       }
     },
+    "ssf": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz",
+      "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
+      "requires": {
+        "frac": "~1.1.2"
+      }
+    },
     "sshpk": {
       "version": "1.17.0",
       "dev": true,
@@ -12385,6 +12517,16 @@
         "isexe": "^2.0.0"
       }
     },
+    "wmf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz",
+      "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
+    },
+    "word": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/word/-/word-0.3.0.tgz",
+      "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
+    },
     "word-wrap": {
       "version": "1.2.3",
       "dev": true
@@ -12407,6 +12549,20 @@
       "dev": true,
       "requires": {}
     },
+    "xlsx": {
+      "version": "0.18.5",
+      "resolved": "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz",
+      "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
+      "requires": {
+        "adler-32": "~1.3.0",
+        "cfb": "~1.2.1",
+        "codepage": "~1.15.0",
+        "crc-32": "~1.2.1",
+        "ssf": "~0.11.2",
+        "wmf": "~1.0.1",
+        "word": "~0.3.0"
+      }
+    },
     "xml-name-validator": {
       "version": "4.0.0",
       "dev": true
diff --git a/package.json b/package.json
index 0f208cb..bf3a30c 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,8 @@
     "pinia": "^2.0.26",
     "vue": "^3.2.45",
     "vue-i18n": "^9.8.0",
-    "vue-router": "^4.1.6"
+    "vue-router": "^4.1.6",
+    "xlsx": "^0.18.5"
   },
   "devDependencies": {
     "@babel/cli": "^7.19.3",
diff --git a/src/api/fysp/dataproductApi.js b/src/api/fysp/dataproductApi.js
new file mode 100644
index 0000000..cdcbf76
--- /dev/null
+++ b/src/api/fysp/dataproductApi.js
@@ -0,0 +1,34 @@
+import { Base64 } from 'js-base64';
+import { $fysp } from '../index';
+
+export default {
+  /**
+   * 涓嬭浇鏁版嵁浜у搧
+   */
+  downloadProduct(area, type, forceUpdate) {
+    return $fysp
+      .post(`dataProduct/download?`, area, {
+        responseType: 'arraybuffer',
+        params: { type, forceUpdate }
+      })
+      .then((res) => {
+        // 鏂囨。鏈敓鎴愶紝宸插惎鍔ㄦ枃妗g敓鎴愬悗鍙颁换鍔�
+        if (res.data.type == 'application/json') {
+          return false;
+        }
+        // 鏂囨。宸插瓨鍦紝杩斿洖鏂囦欢鏁版嵁娴�
+        else {
+          return res.data
+          // const name = Base64.decode(res.headers.get('filename'));
+          // const url = window.URL.createObjectURL(res.data);
+          // const link = document.createElement('a');
+          // link.href = url;
+          // link.setAttribute('download', name);
+          // document.body.appendChild(link);
+          // link.click();
+          // document.body.removeChild(link);
+          // window.URL.revokeObjectURL(url);
+        }
+      });
+  }
+};
diff --git a/src/api/index.js b/src/api/index.js
index 243b99c..231eaba 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -11,7 +11,7 @@
 let ip2_file = 'https://fyami.com.cn/';
 
 if (debug) {
-  ip1 = 'http://192.168.0.138:8080/';
+  ip1 = 'http://192.168.0.138:9001/';
   // ip1_file = 'http://192.168.0.138:8080/';
   // ip2 = 'http://192.168.0.138:8080/';
   // ip2_file = 'https://fyami.com.cn/';
diff --git a/src/components.d.ts b/src/components.d.ts
index 124cacb..13c1bdc 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -12,18 +12,23 @@
     BasePanelLayout: typeof import('./components/core/BasePanelLayout.vue')['default']
     CompQuickSet: typeof import('./components/search-option/CompQuickSet.vue')['default']
     Content: typeof import('./components/core/Content.vue')['default']
+    ElAffix: typeof import('element-plus/es')['ElAffix']
     ElAside: typeof import('element-plus/es')['ElAside']
     ElAvatar: typeof import('element-plus/es')['ElAvatar']
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
     ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCalendar: typeof import('element-plus/es')['ElCalendar']
     ElCard: typeof import('element-plus/es')['ElCard']
+    ElCascader: typeof import('element-plus/es')['ElCascader']
+    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElCollapse: typeof import('element-plus/es')['ElCollapse']
     ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElContainer: typeof import('element-plus/es')['ElContainer']
+    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
     ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
@@ -36,14 +41,19 @@
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElLink: typeof import('element-plus/es')['ElLink']
     ElMain: typeof import('element-plus/es')['ElMain']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
     ElOption: typeof import('element-plus/es')['ElOption']
+    ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
+    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
+    ElSegmented: typeof import('element-plus/es')['ElSegmented']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSpace: typeof import('element-plus/es')['ElSpace']
     ElStep: typeof import('element-plus/es')['ElStep']
@@ -55,6 +65,7 @@
     ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
+    ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     Footer: typeof import('./components/core/Footer.vue')['default']
diff --git a/src/components/core/SiderMenu.vue b/src/components/core/SiderMenu.vue
index abe2269..4e53868 100644
--- a/src/components/core/SiderMenu.vue
+++ b/src/components/core/SiderMenu.vue
@@ -77,7 +77,7 @@
   data() {
     return {
       popVisible: false,
-      menuHeight: '800px',
+      menuHeight: '600px',
       title: '鐢熸�佺幆澧冪嚎涓婄洃绠�',
       subTitle: '漏涓婃捣椋炵窘鐜繚绉戞妧鏈夐檺鍏徃',
       sysIndex: 0,
@@ -139,7 +139,7 @@
     this.navPage(...this.menuPath(this.menus[0]));
   },
   mounted() {
-    // this.menuHeight = this.calMenuHeight();
+    this.menuHeight = this.calMenuHeight();
   }
 };
 </script>
@@ -179,7 +179,7 @@
 .el-menu-vertical-demo:not(.el-menu--collapse) {
   /* width: 200px; */
   min-height: 100vh;
-  /* max-height: 100vh; */
+  max-height: 100vh;
 }
 
 .el-menu--collapse {
diff --git a/src/views/fysp/data-product/ProdProAnalysis.vue b/src/views/fysp/data-product/ProdProAnalysis.vue
index e69de29..2a102cf 100644
--- a/src/views/fysp/data-product/ProdProAnalysis.vue
+++ b/src/views/fysp/data-product/ProdProAnalysis.vue
@@ -0,0 +1,11 @@
+<template>
+  <BaseDataProduct product-type="3"></BaseDataProduct>
+</template>
+<script setup>
+/**
+ * 闂鏁存敼鍒嗘瀽
+ */
+import BaseDataProduct from './components/BaseDataProduct.vue';
+
+
+</script>
diff --git a/src/views/fysp/data-product/ProdProFollow.vue b/src/views/fysp/data-product/ProdProFollow.vue
index e69de29..9819de8 100644
--- a/src/views/fysp/data-product/ProdProFollow.vue
+++ b/src/views/fysp/data-product/ProdProFollow.vue
@@ -0,0 +1,11 @@
+<template>
+  <BaseDataProduct product-type="1"></BaseDataProduct>
+</template>
+<script setup>
+/**
+ * 闂鍔ㄦ�佽窡韪�
+ */
+import BaseDataProduct from './components/BaseDataProduct.vue';
+
+
+</script>
diff --git a/src/views/fysp/data-product/ProdSceneReport.vue b/src/views/fysp/data-product/ProdSceneReport.vue
index e69de29..906fad3 100644
--- a/src/views/fysp/data-product/ProdSceneReport.vue
+++ b/src/views/fysp/data-product/ProdSceneReport.vue
@@ -0,0 +1,3 @@
+<template>
+  鍦烘櫙鎶ュ憡绠$悊
+</template>
\ No newline at end of file
diff --git a/src/views/fysp/data-product/ProdStandardJudge.vue b/src/views/fysp/data-product/ProdStandardJudge.vue
index e69de29..257e617 100644
--- a/src/views/fysp/data-product/ProdStandardJudge.vue
+++ b/src/views/fysp/data-product/ProdStandardJudge.vue
@@ -0,0 +1,11 @@
+<template>
+  <BaseDataProduct product-type="2"></BaseDataProduct>
+</template>
+<script setup>
+/**
+ * 瑙勮寖鎬ц瘎浼�
+ */
+import BaseDataProduct from './components/BaseDataProduct.vue';
+
+
+</script>
diff --git a/src/views/fysp/data-product/components/BaseDataProduct.vue b/src/views/fysp/data-product/components/BaseDataProduct.vue
new file mode 100644
index 0000000..9030b38
--- /dev/null
+++ b/src/views/fysp/data-product/components/BaseDataProduct.vue
@@ -0,0 +1,185 @@
+<template>
+  <FYSearchBar ref="searchRef" @search="handleSearch">
+    <template #options>
+      <!-- 鍖哄幙 -->
+      <FYOptionLocation
+        :allOption="false"
+        :level="3"
+        :checkStrictly="false"
+        v-model:value="formSearch.locations"
+      ></FYOptionLocation>
+      <!-- 鍦烘櫙绫诲瀷 -->
+      <FYOptionScene
+        :allOption="false"
+        :type="2"
+        v-model:value="formSearch.scenetype"
+      ></FYOptionScene>
+      <!-- 鏃堕棿 -->
+      <FYOptionTime
+        :initValue="false"
+        type="month"
+        v-model:value="formSearch.time"
+      ></FYOptionTime>
+    </template>
+    <template #buttons>
+      <CompReportDownloadDialog
+        name="闂涓庢暣鏀规眹鎬诲垎鏋愪笌鍔ㄦ�佽窡韪竻鍗�"
+        :locations="formSearch.locations"
+        :scenetype="formSearch.scenetype"
+        :time="formSearch.time"
+        @submit="handleSearch"
+      ></CompReportDownloadDialog>
+    </template>
+  </FYSearchBar>
+  <el-form ref="expandRef" :inline="true">
+    <CompQuickSet @quick-set="setOptions"></CompQuickSet>
+  </el-form>
+  <el-space>
+    <el-segmented
+      :model-value="activeSheet"
+      :options="sheetNames"
+      @change="tabChange"
+    />
+  </el-space>
+  <el-table
+    ref="tableRef"
+    :data="excelData"
+    v-loading="loading"
+    table-layout="fixed"
+    size="small"
+    :height="tableHeight"
+    border
+  >
+    <template v-if="excelData">
+      <el-table-column
+        v-for="(value, key, index) in excelData[0]"
+        :key="index"
+        :prop="key"
+        :label="key"
+      >
+      </el-table-column>
+    </template>
+  </el-table>
+  <div v-if="excelHtml" v-html="excelHtml"></div>
+</template>
+<script setup>
+/**
+ * 闂鍔ㄦ�佽窡韪�
+ */
+import { ref, onMounted } from 'vue';
+import dayjs from 'dayjs';
+import * as XLSX from 'xlsx';
+import dataproductApi from '@/api/fysp/dataproductApi';
+import CompReportDownloadDialog from './CompReportDownloadDialog.vue';
+
+const emit = defineEmits(['search']);
+
+const props = defineProps({
+  // 鏁版嵁浜у搧绫诲瀷锛�1锛氶棶棰樺姩鎬佽窡韪紱2锛氳鑼冩�ц瘎浼帮紱3锛氶棶棰樻暣鏀瑰垎鏋�
+  productType: Number,
+  // 鍦ㄦ暟鎹睍绀轰箣鍓嶏紝鍋氶澶勭悊锛堜富瑕佹槸澶勭悊鍚堝苟琛ㄥご锛�
+  beforeDataShow: {
+    type: Function,
+    default: (data) => {
+      return data;
+    }
+  },
+  // 鏁版嵁琛ㄦ牸鐨勮〃澶磋鏁�
+  headNum: {
+    type: Number,
+    default: 1
+  }
+});
+
+const formSearch = ref({
+  locations: {},
+  scenetype: {},
+  time: dayjs().add(-1, 'M').date(1).toDate()
+});
+const loading = ref(false);
+const tableHeight = ref('500');
+let workbook;
+const sheetNames = ref();
+const activeSheet = ref();
+const excelData = ref();
+const excelHtml = ref();
+
+const searchRef = ref(null);
+const expandRef = ref(null);
+
+function setOptions(param) {
+  formSearch.value.locations = param.locations;
+  formSearch.value.scenetype = param.scenetype;
+  formSearch.value.sourceType = param.sourceType;
+  handleSearch(false);
+}
+
+function tabChange(tabName) {
+  activeSheet.value = tabName;
+  getTable(activeSheet.value);
+}
+
+function handleSearch(forceUpdate) {
+  const locations = formSearch.value.locations;
+  const time = formSearch.value.time;
+  const scenetype = formSearch.value.scenetype;
+  const area = {
+    provincecode: locations.pCode,
+    provincename: locations.pName,
+    citycode: locations.cCode,
+    cityname: locations.cName,
+    districtcode: locations.dCode,
+    districtname: locations.dName,
+    starttime: dayjs(time).format('YYYY-MM-DD HH:mm:ss'),
+    scensetypeid: scenetype.value
+  };
+
+  loading.value = true;
+  dataproductApi
+    .downloadProduct(area, props.productType, forceUpdate ? forceUpdate : false)
+    .then((res) => {
+      const data = new Uint8Array(res);
+      workbook = XLSX.read(data, { type: 'array' });
+      sheetNames.value = workbook.SheetNames;
+      activeSheet.value = sheetNames.value[0];
+      getTable(activeSheet.value);
+    })
+    .finally(() => (loading.value = false));
+}
+
+function getTable(sheetName) {
+  const worksheet = workbook.Sheets[sheetName];
+  const tableData = XLSX.utils.sheet_to_json(worksheet, { header: 3 });
+  // const tableData = XLSX.utils.sheet_to_csv(worksheet);
+  console.log(tableData);
+  console.log(tableData[0]);
+  combineTableHead(tableData);
+
+  excelData.value = props.beforeDataShow(tableData);
+}
+
+// 鏍规嵁琛ㄥご鐨勮鏁帮紝鍚堝苟琛ㄥご
+function combineTableHead(excelData) {
+  if (excelData.length < props.headNum) return;
+
+  // const newHead = {};
+  // excelData.splice(0, props.headNum).forEach((row) => {
+  //   for (const key in row) {
+  //     console.log(key);
+  //   }
+  // });
+}
+
+function calcTableHeight() {
+  const h1 = searchRef.value.$el.offsetHeight;
+  const h2 = expandRef.value.$el.offsetHeight;
+
+  const h = h1 + h2;
+  return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`;
+}
+
+onMounted(() => {
+  tableHeight.value = calcTableHeight();
+  // handleSearch()
+});
+</script>
diff --git a/src/views/fysp/data-product/components/CompReportDownloadDialog.vue b/src/views/fysp/data-product/components/CompReportDownloadDialog.vue
new file mode 100644
index 0000000..985f669
--- /dev/null
+++ b/src/views/fysp/data-product/components/CompReportDownloadDialog.vue
@@ -0,0 +1,80 @@
+<template>
+  <el-button icon="Download" type="success" @click="dialogVisible = true"
+    >瀵煎嚭鎶ュ憡</el-button
+  >
+  <el-dialog v-model="dialogVisible" :title="name" width="500">
+    <el-text tag="b" size="large">鏁版嵁鑼冨洿纭</el-text>
+    <el-text tag="div">鍖哄煙锛歿{ locationText }}</el-text>
+    <el-text tag="div">绫诲瀷锛歿{ scenetype.label }}</el-text>
+    <el-text tag="div">鏃堕棿锛歿{ timeText }}</el-text>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-row align="middle">
+          <el-checkbox v-model="forceUpdate" label="寮哄埗鐢熸垚鏂版姤鍛�" />
+          <el-tooltip placement="bottom-start" effect="light">
+            <template #content>
+              <el-text tag="b" size="small">涓嶅嬀閫夛細</el-text><br />
+              <el-text size="small"
+                >涓嶅嬀閫夋椂锛屽鏋滃凡鐢熸垚杩囩浉鍚屽尯鍩熺殑鎶ュ憡锛屽垯鐩存帴鑾峰彇璇ヤ唤鎶ュ憡璁板綍</el-text
+              ><br />
+              <el-text tag="b" size="small">鍕鹃�夛細</el-text><br />
+              <el-text size="small"
+                >鍕鹃�夋椂锛屾棤璁烘槸鍚︽湁鍘嗗彶璁板綍锛岄兘浼氬惎鍔ㄦ姤鍛婄敓鎴愪换鍔¤鐩栨棫璁板綍锛屽彲鍦ㄥ悗鍙颁换鍔$晫闈㈡煡鐪嬩换鍔¤繘搴�</el-text
+              ><br />
+            </template>
+            <el-icon
+              class="m-l-8 cursor-p"
+              :size="16"
+              color="var(--el-color-warning)"
+              ><QuestionFilled
+            /></el-icon>
+          </el-tooltip>
+        </el-row>
+        <div>
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="handleSubmit">纭畾</el-button>
+        </div>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+import dayjs from 'dayjs';
+
+export default {
+  props: ['name', 'locations', 'time', 'scenetype'],
+  emits: ['submit'],
+  data() {
+    return {
+      dialogVisible: false,
+      forceUpdate: false
+    };
+  },
+  computed: {
+    locationText() {
+      const loc = this.locations;
+      let text = '';
+      text = loc.pName == loc.cName ? loc.pName : loc.pName + loc.cName;
+      text += loc.dName;
+      return text;
+    },
+    timeText() {
+      return dayjs(this.time).format('YYYY骞碝M鏈�');
+    }
+  },
+  methods: {
+    handleSubmit() {
+      this.$emit('submit', this.forceUpdate);
+    }
+  }
+};
+</script>
+<style scoped>
+.dialog-footer {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  gap: 2px;
+}
+</style>

--
Gitblit v1.9.3