customAnalysis.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. <template>
  2. <div class="content">
  3. <el-tabs
  4. ref="tabs"
  5. tab-position="left"
  6. :active-name="activeName"
  7. style="height: 100%"
  8. @tab-click="handleClick"
  9. >
  10. <el-tab-pane name="import">
  11. <template #label>
  12. <el-popover :visible="showPopover" placement="right" trigger="hover">
  13. <div>
  14. <el-upload
  15. action=""
  16. class="upload-demo"
  17. :http-request="customUpload"
  18. :on-change="handleChange"
  19. :before-upload="checkFileType"
  20. :show-file-list="false"
  21. >
  22. <div class="uploadBoxContent">
  23. <svg-icon
  24. icon-class="table(2)"
  25. style="width: 40px; height: 40px; margin-right: 10px"
  26. />
  27. <span>导入CSV/EXCRL文件</span>
  28. </div>
  29. </el-upload>
  30. </div>
  31. <div class="uploadBoxContent" @click="showDatabaseTable = true">
  32. <svg-icon
  33. icon-class="datasql"
  34. style="width: 40px; height: 30px; margin-right: 10px"
  35. />
  36. <span>数据库导入</span>
  37. </div>
  38. <div
  39. class="iconFont"
  40. style="width: 100%; height: 100%"
  41. slot="reference"
  42. @click.stop="handleImportClick"
  43. >
  44. <svg-icon
  45. icon-class="import(1)"
  46. style="width: 30px; height: 30px"
  47. />
  48. </div>
  49. </el-popover>
  50. </template>
  51. </el-tab-pane>
  52. <el-tab-pane name="chart" class="chartsTab">
  53. <span slot="label" class="iconFont">
  54. <el-tooltip
  55. class="item"
  56. effect="dark"
  57. content="自定义图表"
  58. placement="right"
  59. >
  60. <span>
  61. <svg-icon
  62. icon-class="table(1)"
  63. style="width: 30px; height: 30px"
  64. />
  65. </span>
  66. </el-tooltip>
  67. </span>
  68. <DragChart></DragChart>
  69. </el-tab-pane>
  70. <el-tab-pane name="table">
  71. <span slot="label" class="iconFont">
  72. <el-tooltip
  73. class="item"
  74. effect="dark"
  75. content="数据表格"
  76. placement="right"
  77. >
  78. <span>
  79. <svg-icon
  80. icon-class="table(3)"
  81. style="width: 30px; height: 30px"
  82. />
  83. </span>
  84. </el-tooltip>
  85. </span>
  86. <DataTable ref="dataTableRef"></DataTable>
  87. </el-tab-pane>
  88. <el-tab-pane name="compute">
  89. <span slot="label" class="iconFont" @click.stop="dialogVisible = true">
  90. <el-tooltip
  91. class="item"
  92. effect="dark"
  93. content="自定义算法调用"
  94. placement="right"
  95. >
  96. <span>
  97. <svg-icon
  98. icon-class="compute(1)"
  99. style="width: 30px; height: 30px"
  100. />
  101. </span>
  102. </el-tooltip>
  103. </span>
  104. 计算器弹出框
  105. </el-tab-pane>
  106. <el-tab-pane name="associatedFields">
  107. <span slot="label" class="iconFont">
  108. <el-tooltip
  109. class="item"
  110. effect="dark"
  111. content="数据关联"
  112. placement="right"
  113. >
  114. <span>
  115. <svg-icon
  116. icon-class="associatedFields"
  117. style="width: 30px; height: 30px"
  118. />
  119. </span>
  120. </el-tooltip>
  121. </span>
  122. <AssociatedFields></AssociatedFields>
  123. </el-tab-pane>
  124. </el-tabs>
  125. <el-dialog
  126. title="数据列表特征计算函数"
  127. :visible.sync="dialogVisible"
  128. width="600px"
  129. :before-close="handleClose"
  130. >
  131. <el-form
  132. :model="ruleForm"
  133. :rules="rules"
  134. ref="ruleForm"
  135. label-width="140px"
  136. class="demo-ruleForm"
  137. >
  138. <el-form-item label="选择数据列表:" prop="region">
  139. <el-select
  140. v-model="ruleForm.region"
  141. placeholder="请选择活动区域"
  142. size="small"
  143. >
  144. <el-option label="区域一" value="shanghai"></el-option>
  145. <el-option label="区域二" value="beijing"></el-option>
  146. </el-select>
  147. </el-form-item>
  148. <el-form-item label="选择特征值计算:" prop="type">
  149. <el-checkbox-group v-model="ruleForm.type">
  150. <el-checkbox label="有效值" name="type"></el-checkbox>
  151. <el-checkbox label="平均值" name="type"></el-checkbox>
  152. <el-checkbox label="最大值" name="type"></el-checkbox>
  153. <el-checkbox label="最小值" name="type"></el-checkbox>
  154. <el-checkbox label="峰值" name="type"></el-checkbox>
  155. <el-checkbox label="峰峰值" name="type"></el-checkbox>
  156. <el-checkbox label="峰值指标" name="type"></el-checkbox>
  157. <el-checkbox label="峰度指标" name="type"></el-checkbox>
  158. <el-checkbox label="歪度指标" name="type"></el-checkbox>
  159. <el-checkbox label="裕度指标" name="type"></el-checkbox>
  160. <el-checkbox label="脉冲指标" name="type"></el-checkbox>
  161. <el-checkbox label="波形指标" name="type"></el-checkbox>
  162. </el-checkbox-group>
  163. </el-form-item>
  164. </el-form>
  165. <span slot="footer" class="dialog-footer">
  166. <el-button @click="dialogVisible = false">取 消</el-button>
  167. <el-button type="primary" @click="dialogVisible = false"
  168. >确 定</el-button
  169. >
  170. </span>
  171. </el-dialog>
  172. <DatabaseTable
  173. :dialogVisible="showDatabaseTable"
  174. @closeDialog="showDatabaseTable = false"
  175. ></DatabaseTable>
  176. </div>
  177. </template>
  178. <script>
  179. import DataTable from "./components/custonAsCom/dataTable.vue";
  180. import DatabaseTable from "./components/custonAsCom/DatabaseTable.vue";
  181. import DragChart from "./components/custonAsCom/dragChart/index.vue";
  182. import AssociatedFields from "./components/custonAsCom/AssociatedFields.vue";
  183. import Papa from "papaparse";
  184. import * as XLSX from "xlsx";
  185. import { storeSetData } from "@/utils/indexedDb";
  186. import { format } from "date-fns";
  187. import { mapMutations, mapState } from "vuex";
  188. export default {
  189. components: {
  190. DataTable,
  191. DatabaseTable,
  192. DragChart,
  193. AssociatedFields,
  194. },
  195. data() {
  196. return {
  197. db: null,
  198. activeName: "chart",
  199. showDatabaseTable: false,
  200. showPopover: false, // 控制 popover 的显示状态
  201. dialogVisible: false, //计算函数对话框状态
  202. ruleForm: {
  203. region: "",
  204. type: [],
  205. },
  206. rules: {
  207. region: [
  208. {
  209. required: true,
  210. message: "请至少选择一个数据列表!",
  211. trigger: "change",
  212. },
  213. ],
  214. type: [
  215. {
  216. type: "array",
  217. required: true,
  218. message: "请至少选择一个特征值进行计算!",
  219. trigger: "change",
  220. },
  221. ],
  222. },
  223. };
  224. },
  225. computed: {
  226. ...mapState("dragChart", {
  227. updateTriggerGetData: "updateTriggerGetData",
  228. }),
  229. },
  230. watch: {
  231. updateTriggerGetData: function (newVal) {
  232. if (newVal) {
  233. console.log(newVal, "newVal dataTable");
  234. this.setUpdateTriggerGetData(false);
  235. this.$refs.dataTableRef.getIndexDbData();
  236. // 重置 triggerGetData 状态为 false
  237. }
  238. },
  239. },
  240. methods: {
  241. ...mapMutations("dragChart", [
  242. "setTriggerGetData",
  243. "setUpdateTriggerGetData",
  244. ]),
  245. async initDB() {
  246. return new Promise((resolve, reject) => {
  247. const request = indexedDB.open("FileDataDB", 2); // 使用较高版本
  248. request.onupgradeneeded = (event) => {
  249. const db = event.target.result;
  250. console.log("升级数据库,创建对象存储。");
  251. // 检查是否存在对象存储
  252. if (!db.objectStoreNames.contains("files")) {
  253. db.createObjectStore("files", { keyPath: "id" });
  254. }
  255. };
  256. request.onsuccess = (event) => {
  257. this.db = event.target.result;
  258. console.log("数据库已成功初始化。");
  259. resolve();
  260. };
  261. request.onerror = (event) => {
  262. console.error("数据库初始化失败:", event.target.error);
  263. reject(event.target.error);
  264. };
  265. });
  266. },
  267. async storeData(newFileData) {
  268. await storeSetData(this.db, "files", "fileDataArray", newFileData, () => {
  269. this.setTriggerGetData(true);
  270. this.$refs.dataTableRef.getIndexDbData();
  271. });
  272. },
  273. handleClose(done) {
  274. this.$confirm("确认关闭?")
  275. .then((_) => {
  276. done();
  277. })
  278. .catch((_) => {});
  279. },
  280. handleImportClick() {
  281. // 点击 import 标签时切换 popover 的显示状态
  282. this.showPopover = !this.showPopover; // 切换显示状态
  283. },
  284. handleClick(tab) {
  285. if (tab.name === "import") {
  286. // 如果点击的是 import 标签,则显示 popover
  287. this.showPopover = true;
  288. } else {
  289. // 其他标签时,改变 activeName
  290. this.activeName = tab.name;
  291. }
  292. },
  293. // 自定义上传方法
  294. customUpload(file) {
  295. const formData = new FormData();
  296. formData.append("file", file);
  297. // 使用 axios 自定义上传逻辑
  298. },
  299. // 文件变化时的处理
  300. handleChange(file) {
  301. if (file && file.name.endsWith(".csv")) {
  302. Papa.parse(file.raw, {
  303. header: true,
  304. complete: (results) => {
  305. // 可以进一步处理解析后的数据
  306. const fileData = {
  307. filename: format(new Date(), "yyyyMMdd-HH:mm:ss") + file.name,
  308. fileOldName: file.name,
  309. fileData: results.data,
  310. fileId: new Date().getTime(),
  311. };
  312. if (results.data.length > 0) {
  313. this.storeData(fileData);
  314. }
  315. },
  316. error: (error) => {
  317. console.error("Error parsing CSV:", error);
  318. },
  319. });
  320. } else {
  321. const reader = new FileReader();
  322. reader.onload = (e) => {
  323. const data = new Uint8Array(e.target.result);
  324. const workbook = XLSX.read(data, { type: "array" });
  325. workbook.SheetNames.forEach((sheetName) => {
  326. const sheetData = XLSX.utils.sheet_to_json(
  327. workbook.Sheets[sheetName]
  328. );
  329. const fileData = {
  330. filename: format(new Date(), "yyyyMMdd-HH:mm:ss") + file.name,
  331. fileData: sheetData,
  332. fileOldName: file.name,
  333. fileId: new Date().getTime(),
  334. };
  335. if (sheetData.length > 0) {
  336. this.storeData(fileData);
  337. }
  338. // console.log("Parsed Excel Sheet Data:", sheetData);
  339. // 可以进一步处理解析后的数据
  340. });
  341. };
  342. reader.readAsArrayBuffer(file.raw);
  343. }
  344. },
  345. //判断上传文件类型
  346. checkFileType(file) {
  347. const isPdf =
  348. file.type === "text/csv" ||
  349. file.name.endsWith(".csv") ||
  350. file.type ===
  351. "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ||
  352. file.name.endsWith(".xlsx");
  353. if (!isPdf) {
  354. this.$message.error("只能上传csv文件或xlsx文件");
  355. }
  356. return isPdf;
  357. },
  358. },
  359. async mounted() {
  360. await this.initDB(); // 初始化数据库
  361. },
  362. };
  363. </script>
  364. <style scoped lang="scss">
  365. .content {
  366. width: 100%;
  367. height: 88vh;
  368. ::v-deep .el-tabs__active-bar {
  369. // height: 50px !important;
  370. transition: transform 0.3s ease; // 添加过渡效果
  371. }
  372. ::v-deep .el-tabs--left .el-tabs__item {
  373. height: 55px;
  374. line-height: 55px;
  375. }
  376. ::v-deep .el-tabs__item {
  377. padding: 0;
  378. }
  379. .popover-footer {
  380. text-align: right;
  381. }
  382. .iconFont {
  383. padding: 0 20px;
  384. }
  385. ::v-deep .el-tabs__content {
  386. height: 100% !important;
  387. }
  388. .chartsTab {
  389. width: 100%;
  390. height: 100%;
  391. }
  392. }
  393. .uploadBoxContent {
  394. margin: 5px;
  395. display: flex;
  396. flex-direction: 1;
  397. align-items: center;
  398. cursor: pointer;
  399. }
  400. </style>