From f5052fa7d4e73c0df5a02a6ad8987f35df42b8f8 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期四, 07 十一月 2024 17:23:50 +0800 Subject: [PATCH] 1. 完成场景报告模块 2. 日报管理模块添加时间范围选择以及word报告生成 --- src/enum/device/monitorDevice.js | 12 package-lock.json | 140 +++++++ src/components/search-option/FYOptionTime.vue | 1 src/components.d.ts | 16 src/composables/formConfirm.js | 2 src/constants/menu.js | 62 +- src/views/fysp/data-product/components/CompImgInfo.vue | 41 + src/components/search-option/FYOptionLocation.vue | 1 src/utils/doc.js | 96 +++++ src/views/fysp/check/components/ArbitraryPhoto.vue | 4 src/views/fysp/data-product/components/CompProblemTable.vue | 28 + src/api/index.js | 2 src/assets/image/right_triangle.png | 0 public/单体模版(静安).docx | 0 src/views/fysp/data-product/ProdSceneReport.vue | 156 +++++++ public/单体模版.docx | 0 src/views/DocTest.vue | 70 +++ public/秋冬季空气质量攻坚工作提示模板.docx | 0 src/views/fysp/scene/CompSceneConstructionInfo.vue | 70 +++ src/views/fysp/check/components/CompDevicePhono.vue | 9 src/router/index.js | 6 src/views/fysp/check/components/CompDevicePhoto.vue | 53 ++ src/api/fysp/analysisApi.js | 2 src/components/FYImageSelectDialog.vue | 3 package.json | 7 src/views/fysp/data-product/ProdDailyReport.vue | 344 +++++++---------- 26 files changed, 849 insertions(+), 276 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9c38877..2cacd5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,12 +15,19 @@ "@vueuse/core": "^9.7.0", "axios": "^1.2.1", "dayjs": "^1.11.13", + "docxtemplater": "^3.50.0", + "docxtemplater-image-module": "^3.1.0", + "docxtemplater-image-module-free": "^1.1.1", "element-plus": "^2.8.3", "exceljs": "^4.4.0", "file-saver": "^2.0.5", "js-base64": "^3.7.5", + "jszip": "^3.10.1", + "jszip-utils": "^0.1.0", "md5": "^2.3.0", + "open-docxtemplater-image-module": "^1.0.3", "pinia": "^2.0.26", + "pizzip": "^3.1.7", "vue": "^3.2.45", "vue-demi": "^0.14.6", "vue-i18n": "^9.8.0", @@ -2737,6 +2744,14 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "dev": true, @@ -3932,6 +3947,34 @@ }, "engines": { "node": ">=6.0.0" + } + }, + "node_modules/docxtemplater": { + "version": "3.50.0", + "resolved": "https://registry.npmmirror.com/docxtemplater/-/docxtemplater-3.50.0.tgz", + "integrity": "sha512-6EqYbBFUcdNKVwS6G8vQ+pFOURJ7zoSvUNASIi4MPnCpkRdYDvmaOV2e1XcScMrEQV5pFZUAAbKi30Z+JTbLFA==", + "dependencies": { + "@xmldom/xmldom": "^0.8.10" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/docxtemplater-image-module": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/docxtemplater-image-module/-/docxtemplater-image-module-3.1.0.tgz", + "integrity": "sha512-dFzuGOhCXgZpzAO7hGJvGbjzUCvid+3L4lSjbBta+TnXuBb/55pqDQWeRZ38yMviu+QTaYreSHHdYHF1XvQlBA==", + "deprecated": "This module has been deprecated, No new releases will be made to it.\n\nThere is an up to date paid version of the module which you can find on https://docxtemplater.com/modules/image/", + "dependencies": { + "xmldom": "^0.1.27" + } + }, + "node_modules/docxtemplater-image-module-free": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/docxtemplater-image-module-free/-/docxtemplater-image-module-free-1.1.1.tgz", + "integrity": "sha512-aWOzVQN7ggDYjfoy3pTTNrcrZ7/CJrQcI9cT+hmyHE6nRLR67nt5yPFPe9hm9VWbfYIED2fi+3itOnF0TE/RWQ==", + "dependencies": { + "xmldom": "^0.1.27" } }, "node_modules/domexception": { @@ -5573,6 +5616,11 @@ "setimmediate": "^1.0.5" } }, + "node_modules/jszip-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/jszip-utils/-/jszip-utils-0.1.0.tgz", + "integrity": "sha512-tBNe0o3HAf8vo0BrOYnLPnXNo5A3KsRMnkBFYjh20Y3GPYGfgyoclEMgvVchx0nnL+mherPi74yLPIusHUQpZg==" + }, "node_modules/jszip/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", @@ -6227,6 +6275,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open-docxtemplater-image-module": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/open-docxtemplater-image-module/-/open-docxtemplater-image-module-1.0.3.tgz", + "integrity": "sha512-/VMRc8MU34T2/ry2ER0+/JXjc4BTuWDtdXlqnWo5ikR/DvsLVAjF6F8094dA7+i68cfDrGgP42VEXqbwyLaTdg==", + "dependencies": { + "xmldom": "^0.1.27" + } + }, "node_modules/optionator": { "version": "0.9.1", "dev": true, @@ -6437,6 +6493,19 @@ "optional": true } } + }, + "node_modules/pizzip": { + "version": "3.1.7", + "resolved": "https://registry.npmmirror.com/pizzip/-/pizzip-3.1.7.tgz", + "integrity": "sha512-VemVeAQtdIA74AN1Fsd5OmbMbEeS4YOwwlcudgzvmUrOIOPrk1idYC5Tw5FUFq/I0c26ziNOw9z//iPmGfp1jA==", + "dependencies": { + "pako": "^2.1.0" + } + }, + "node_modules/pizzip/node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" }, "node_modules/postcss": { "version": "8.4.20", @@ -8296,6 +8365,15 @@ "version": "2.2.0", "license": "MIT" }, + "node_modules/xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmmirror.com/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0", + "engines": { + "node": ">=0.1" + } + }, "node_modules/yallist": { "version": "4.0.0", "dev": true, @@ -10123,6 +10201,11 @@ "@xtuc/long": "4.2.2" } }, + "@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==" + }, "@xtuc/ieee754": { "version": "1.2.0", "dev": true, @@ -10883,6 +10966,30 @@ "dev": true, "requires": { "esutils": "^2.0.2" + } + }, + "docxtemplater": { + "version": "3.50.0", + "resolved": "https://registry.npmmirror.com/docxtemplater/-/docxtemplater-3.50.0.tgz", + "integrity": "sha512-6EqYbBFUcdNKVwS6G8vQ+pFOURJ7zoSvUNASIi4MPnCpkRdYDvmaOV2e1XcScMrEQV5pFZUAAbKi30Z+JTbLFA==", + "requires": { + "@xmldom/xmldom": "^0.8.10" + } + }, + "docxtemplater-image-module": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/docxtemplater-image-module/-/docxtemplater-image-module-3.1.0.tgz", + "integrity": "sha512-dFzuGOhCXgZpzAO7hGJvGbjzUCvid+3L4lSjbBta+TnXuBb/55pqDQWeRZ38yMviu+QTaYreSHHdYHF1XvQlBA==", + "requires": { + "xmldom": "^0.1.27" + } + }, + "docxtemplater-image-module-free": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/docxtemplater-image-module-free/-/docxtemplater-image-module-free-1.1.1.tgz", + "integrity": "sha512-aWOzVQN7ggDYjfoy3pTTNrcrZ7/CJrQcI9cT+hmyHE6nRLR67nt5yPFPe9hm9VWbfYIED2fi+3itOnF0TE/RWQ==", + "requires": { + "xmldom": "^0.1.27" } }, "domexception": { @@ -12006,6 +12113,11 @@ } } }, + "jszip-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/jszip-utils/-/jszip-utils-0.1.0.tgz", + "integrity": "sha512-tBNe0o3HAf8vo0BrOYnLPnXNo5A3KsRMnkBFYjh20Y3GPYGfgyoclEMgvVchx0nnL+mherPi74yLPIusHUQpZg==" + }, "klona": { "version": "2.0.5", "dev": true @@ -12437,6 +12549,14 @@ "mimic-fn": "^2.1.0" } }, + "open-docxtemplater-image-module": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/open-docxtemplater-image-module/-/open-docxtemplater-image-module-1.0.3.tgz", + "integrity": "sha512-/VMRc8MU34T2/ry2ER0+/JXjc4BTuWDtdXlqnWo5ikR/DvsLVAjF6F8094dA7+i68cfDrGgP42VEXqbwyLaTdg==", + "requires": { + "xmldom": "^0.1.27" + } + }, "optionator": { "version": "0.9.1", "dev": true, @@ -12553,6 +12673,21 @@ "requires": { "@vue/devtools-api": "^6.4.5", "vue-demi": "*" + } + }, + "pizzip": { + "version": "3.1.7", + "resolved": "https://registry.npmmirror.com/pizzip/-/pizzip-3.1.7.tgz", + "integrity": "sha512-VemVeAQtdIA74AN1Fsd5OmbMbEeS4YOwwlcudgzvmUrOIOPrk1idYC5Tw5FUFq/I0c26ziNOw9z//iPmGfp1jA==", + "requires": { + "pako": "^2.1.0" + }, + "dependencies": { + "pako": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + } } }, "postcss": { @@ -13665,6 +13800,11 @@ "xmlchars": { "version": "2.2.0" }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmmirror.com/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" + }, "yallist": { "version": "4.0.0", "dev": true diff --git a/package.json b/package.json index 99f30e6..3b8fb9b 100644 --- a/package.json +++ b/package.json @@ -20,12 +20,19 @@ "@vueuse/core": "^9.7.0", "axios": "^1.2.1", "dayjs": "^1.11.13", + "docxtemplater": "^3.50.0", + "docxtemplater-image-module": "^3.1.0", + "docxtemplater-image-module-free": "^1.1.1", "element-plus": "^2.8.3", "exceljs": "^4.4.0", "file-saver": "^2.0.5", "js-base64": "^3.7.5", + "jszip": "^3.10.1", + "jszip-utils": "^0.1.0", "md5": "^2.3.0", + "open-docxtemplater-image-module": "^1.0.3", "pinia": "^2.0.26", + "pizzip": "^3.1.7", "vue": "^3.2.45", "vue-demi": "^0.14.6", "vue-i18n": "^9.8.0", diff --git "a/public/\345\215\225\344\275\223\346\250\241\347\211\210.docx" "b/public/\345\215\225\344\275\223\346\250\241\347\211\210.docx" new file mode 100644 index 0000000..364871a --- /dev/null +++ "b/public/\345\215\225\344\275\223\346\250\241\347\211\210.docx" Binary files differ diff --git "a/public/\345\215\225\344\275\223\346\250\241\347\211\210\357\274\210\351\235\231\345\256\211\357\274\211.docx" "b/public/\345\215\225\344\275\223\346\250\241\347\211\210\357\274\210\351\235\231\345\256\211\357\274\211.docx" new file mode 100644 index 0000000..e592286 --- /dev/null +++ "b/public/\345\215\225\344\275\223\346\250\241\347\211\210\357\274\210\351\235\231\345\256\211\357\274\211.docx" Binary files differ diff --git "a/public/\347\247\213\345\206\254\345\255\243\347\251\272\346\260\224\350\264\250\351\207\217\346\224\273\345\235\232\345\267\245\344\275\234\346\217\220\347\244\272\346\250\241\346\235\277.docx" "b/public/\347\247\213\345\206\254\345\255\243\347\251\272\346\260\224\350\264\250\351\207\217\346\224\273\345\235\232\345\267\245\344\275\234\346\217\220\347\244\272\346\250\241\346\235\277.docx" new file mode 100644 index 0000000..20ea4b8 --- /dev/null +++ "b/public/\347\247\213\345\206\254\345\255\243\347\251\272\346\260\224\350\264\250\351\207\217\346\224\273\345\235\232\345\267\245\344\275\234\346\217\220\347\244\272\346\250\241\346\235\277.docx" Binary files differ diff --git a/src/api/fysp/analysisApi.js b/src/api/fysp/analysisApi.js index 35a3078..3123131 100644 --- a/src/api/fysp/analysisApi.js +++ b/src/api/fysp/analysisApi.js @@ -1,7 +1,7 @@ import { $fysp } from '../index'; export default { - checkProblem(data) { + dailyreport(data) { return $fysp.post(`search/dailyreport`, data).then((res) => res.data); }, } \ No newline at end of file diff --git a/src/api/index.js b/src/api/index.js index 231eaba..81c0cff 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -1,7 +1,7 @@ import axios from 'axios'; import { ElMessage } from 'element-plus'; -const debug = true; +const debug = false; let ip1 = 'http://47.100.191.150:9005/'; let ip1_file = 'http://47.100.191.150:9005/'; diff --git a/src/assets/image/right_triangle.png b/src/assets/image/right_triangle.png new file mode 100644 index 0000000..aab1fcd --- /dev/null +++ b/src/assets/image/right_triangle.png Binary files differ diff --git a/src/components.d.ts b/src/components.d.ts index f9748ca..7d97466 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -12,14 +12,18 @@ 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'] + ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] + 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'] @@ -31,6 +35,9 @@ ElDialog: typeof import('element-plus/es')['ElDialog'] ElDivider: typeof import('element-plus/es')['ElDivider'] ElDrawer: typeof import('element-plus/es')['ElDrawer'] + ElDropdown: typeof import('element-plus/es')['ElDropdown'] + ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] + ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] ElEmpty: typeof import('element-plus/es')['ElEmpty'] ElForm: typeof import('element-plus/es')['ElForm'] ElFormItem: typeof import('element-plus/es')['ElFormItem'] @@ -38,21 +45,29 @@ ElIcon: typeof import('element-plus/es')['ElIcon'] ElImage: typeof import('element-plus/es')['ElImage'] ElInput: typeof import('element-plus/es')['ElInput'] + ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] + 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'] + ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] + ElPagination: typeof import('element-plus/es')['ElPagination'] + ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm'] ElPopover: typeof import('element-plus/es')['ElPopover'] + ElRadio: typeof import('element-plus/es')['ElRadio'] 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'] ElSteps: typeof import('element-plus/es')['ElSteps'] ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] + ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTabPane: typeof import('element-plus/es')['ElTabPane'] @@ -60,6 +75,7 @@ ElTag: typeof import('element-plus/es')['ElTag'] ElText: typeof import('element-plus/es')['ElText'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] + ElTransfer: typeof import('element-plus/es')['ElTransfer'] 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/FYImageSelectDialog.vue b/src/components/FYImageSelectDialog.vue index 744b866..8eb1bc6 100644 --- a/src/components/FYImageSelectDialog.vue +++ b/src/components/FYImageSelectDialog.vue @@ -4,7 +4,6 @@ @opened="$emit('update:dialogVisible', true)" @closed="$emit('update:dialogVisible', false)" width="66%" - title="浠绘剰鍥剧墖" destroy-on-close > <div class="main"> @@ -30,7 +29,7 @@ v-for="item in typeList" :key="item.typeId" :label=" - item.typeName + ' (' + typeImgMap.get(activeId).length + ')' + item.typeName + ' (' + typeImgMap.get(item.typeId).length + ')' " :name="item.typeId" > diff --git a/src/components/search-option/FYOptionLocation.vue b/src/components/search-option/FYOptionLocation.vue index 821cb2a..cf5cee9 100644 --- a/src/components/search-option/FYOptionLocation.vue +++ b/src/components/search-option/FYOptionLocation.vue @@ -7,6 +7,7 @@ :placeholder="placeholder" :props="optionProps" style="width: 320px" + v-bind="$attrs" /> </el-form-item> </template> diff --git a/src/components/search-option/FYOptionTime.vue b/src/components/search-option/FYOptionTime.vue index 82e2a64..b745a32 100644 --- a/src/components/search-option/FYOptionTime.vue +++ b/src/components/search-option/FYOptionTime.vue @@ -8,6 +8,7 @@ start-placeholder="閫夋嫨寮�濮嬫椂闂�" end-placeholder="閫夋嫨缁撴潫鏃堕棿" style="width: 150px" + v-bind="$attrs" /> </el-form-item> </template> diff --git a/src/composables/formConfirm.js b/src/composables/formConfirm.js index 92d114c..e1eafd1 100644 --- a/src/composables/formConfirm.js +++ b/src/composables/formConfirm.js @@ -13,7 +13,7 @@ }, reset = { do: () => {} - } + }, }) { if (!submit.title) submit.title = '鎻愪氦'; if (!submit.msg) submit.msg = '纭鏄惁鎻愪氦锛�'; diff --git a/src/constants/menu.js b/src/constants/menu.js index 6add49c..9f44cb9 100644 --- a/src/constants/menu.js +++ b/src/constants/menu.js @@ -4,7 +4,15 @@ icon: 'Connection', name: '璐︽埛鍖归厤' } -] +]; + +if (import.meta.env.DEV) { + MENU_COMMON.push({ + path: '/common/docTest', + icon: 'Connection', + name: '鏂囨。鐢熸垚' + }); +} const MENU_FYSP = [ // { @@ -26,14 +34,14 @@ { path: '/fysp/task/manage', icon: 'CircleCheck', - name: '鐩戠浠诲姟', + name: '鐩戠浠诲姟' }, { path: '/fysp/sceneInfo', icon: 'Files', - name: '鍦烘櫙淇℃伅', - }, - ], + name: '鍦烘櫙淇℃伅' + } + ] }, { icon: 'DataAnalysis', @@ -42,24 +50,24 @@ { path: '/fysp/data-product/profollow', icon: 'Document', - name: '闂鍔ㄦ�佽窡韪�', + name: '闂鍔ㄦ�佽窡韪�' }, { path: '/fysp/data-product/proanalysis', icon: 'Document', - name: '闂鏁存敼鍒嗘瀽', + name: '闂鏁存敼鍒嗘瀽' }, { path: '/fysp/data-product/standardjudge', icon: 'Document', - name: '瑙勮寖鎬ц瘎浼�', + name: '瑙勮寖鎬ц瘎浼�' }, { path: '/fysp/data-product/dailyreport', icon: 'Document', - name: '鏃ユ姤绠$悊', - }, - ], + name: '鏃ユ姤绠$悊' + } + ] }, { icon: 'DataAnalysis', @@ -68,9 +76,9 @@ { path: '/fysp/data-product/scenereport', icon: 'Document', - name: '鍦烘櫙鎶ュ憡', - }, - ], + name: '鍦烘櫙鎶ュ憡' + } + ] }, // { // path: '/changecheck', @@ -84,14 +92,14 @@ { path: '/fysp/evaluation/evalutationTask', icon: 'MessageBox', - name: '璇勪及浠诲姟', + name: '璇勪及浠诲姟' }, { path: '/fysp/evaluation/evalutationRecord', icon: 'Tickets', - name: '璇勪及璁板綍', - }, - ], + name: '璇勪及璁板綍' + } + ] }, { icon: 'Setting', @@ -100,20 +108,20 @@ { path: '/fysp/config/problemType', icon: 'List', - name: '鐩戠闂', + name: '鐩戠闂' }, { path: '/fysp/config/deviceMatch', icon: 'List', - name: '璁惧鍖归厤', + name: '璁惧鍖归厤' }, { //璇勪及瑙勫垯绠$悊 path: '/fysp/config/evalutationRule', icon: 'List', - name: '璇勪及瑙勫垯', - }, - ], + name: '璇勪及瑙勫垯' + } + ] }, { path: '/fysp/support', @@ -166,7 +174,7 @@ // ] // }, ...MENU_COMMON -] +]; const MENU_FYTZ = [ { @@ -196,7 +204,7 @@ ] }, ...MENU_COMMON -] +]; const MENU_FYPW = [ { @@ -204,6 +212,6 @@ icon: 'Search', name: '鎺掓薄鎶借繍' } -] +]; -export { MENU_FYSP, MENU_FYTZ, MENU_FYPW, MENU_COMMON } +export { MENU_FYSP, MENU_FYTZ, MENU_FYPW, MENU_COMMON }; diff --git a/src/enum/device/monitorDevice.js b/src/enum/device/monitorDevice.js index 987b173..76cd9c8 100644 --- a/src/enum/device/monitorDevice.js +++ b/src/enum/device/monitorDevice.js @@ -1,10 +1,10 @@ const dustDeviceType = [ { - label: '鎵皹鐩戞祴', + label: '鎵皹', value: '1', children: [ { - label: '鎵皹鐩戞祴', + label: '鐩戞祴璁惧', value: '1', }, ], @@ -13,11 +13,11 @@ const fumeDeviceType = [ { - label: '娌圭儫鐩戞祴', + label: '娌圭儫', value: '1', children: [ { - label: '娌圭儫鐩戞祴', + label: '鐩戞祴璁惧', value: '1', }, ], @@ -26,11 +26,11 @@ const vocDeviceType = [ { - label: 'VOC鐩戞祴', + label: 'VOC', value: '1', children: [ { - label: 'VOC鐩戞祴', + label: '鐩戞祴璁惧', value: '1', }, ], diff --git a/src/router/index.js b/src/router/index.js index 41e3ccd..6a36171 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -202,6 +202,12 @@ name: 'userMatch', path: '/common/userMatch', component: () => import('@/views/common/UserMatch.vue') + }, + { + //鏂囨。鐢熸垚娴嬭瘯 + name: 'docTest', + path: '/common/docTest', + component: () => import('@/views/DocTest.vue') } ] diff --git a/src/utils/doc.js b/src/utils/doc.js new file mode 100644 index 0000000..5e30908 --- /dev/null +++ b/src/utils/doc.js @@ -0,0 +1,96 @@ +import JSZipUtils from 'jszip-utils'; +import JSZip from 'jszip'; +import docxtemplater from 'docxtemplater'; +import ImageModule from 'docxtemplater-image-module-free'; +import Pizzip from 'pizzip'; +import PizZipUtils from 'pizzip/utils/dist/pizzip-utils'; +import FileSaver from 'file-saver'; +import fs from 'fs'; + +/** + * 鑾峰彇鍥剧墖閰嶇疆淇℃伅 + * @param {Number} horizontalHeight 鍥剧墖瀹藉害澶т簬楂樺害鏃讹紝闄愬埗鍏堕珮搴� + * @param {Number} verticalWidth 鍥剧墖瀹藉害灏忎簬楂樺害鏃讹紝闄愬埗鍏跺搴� + * @returns + */ +function getImageOptions(options) { + const horizontalHeight = options ? options.horizontalHeight : undefined + const verticalWidth = options ? options.verticalWidth : undefined + return { + centered: false, + fileType: 'docx', + getImage(tagValue) { + // In this case tagValue will be a URL tagValue = "https://docxtemplater.com/puffin.png" + return new Promise(function (resolve, reject) { + JSZipUtils.getBinaryContent(tagValue, function (error, content) { + if (error) { + return reject(error); + } + return resolve(content); + }); + }); + }, + getSize(img, tagValue, tagName) { + return new Promise(function (resolve, reject) { + const image = new Image(); + image.src = tagValue; + image.onload = function () { + let width = image.width; + let height = image.height; + // console.log('width height', width, height); + + if (width > height && horizontalHeight && height > horizontalHeight) { + const scale = image.height / horizontalHeight; + height = horizontalHeight; + width = image.width / scale; + } else if (width <= height && verticalWidth && width > verticalWidth) { + const scale = image.width / verticalWidth; + width = verticalWidth; + height = image.height / scale; + } + // console.log('scale', width, height); + + resolve([width, height]); + }; + image.onerror = function (e) { + console.log('img, tagValue, tagName : ', img, tagValue, tagName); + alert('An error occured while loading ' + tagValue); + reject(e); + }; + }); + } + }; +} + +export const exportDocx = (tempDocpath, data, zipName, imageSize) => { + return new Promise((resolve, reject) => { + JSZipUtils.getBinaryContent(tempDocpath, (error, content) => { + if (error) { + reject(error); + throw error; + } + const zip = new Pizzip(content); + const imageOptions = getImageOptions(imageSize); + let doc = new docxtemplater() + .setOptions({ paragraphLoop: true }) + .loadZip(zip) + .attachModule(new ImageModule(imageOptions)) + .compile(); + doc.resolveData(data).then(() => { + try { + doc.render(); + } catch (error) { + console.log(error); + throw error; + } + const out = doc.getZip().generate({ + type: 'blob', + mimeType: + 'application/vnd.openxmlformats-officedocumnet.wordprocessingml.document' + }); + FileSaver.saveAs(out, zipName); + resolve(); + }); + }); + }); +}; diff --git a/src/views/DocTest.vue b/src/views/DocTest.vue new file mode 100644 index 0000000..d4e59bf --- /dev/null +++ b/src/views/DocTest.vue @@ -0,0 +1,70 @@ +<template> + <div> + <el-button type="primary" @click="export_doc">瀵煎嚭鏂囨。</el-button> + </div> +</template> +<script setup> +import { exportDocx } from '@/utils/doc'; + +const param = { + month: 11, + day: 4, + index: 5, + hasMoreDays: false, + endMonth: 11, + endDay: 6, + totalScene: 16, + sceneNumTxt: '宸ュ湴10涓�佺爜澶�6涓�', + proNum: 23, + changeNum: 19, + unChangeNum: 4, + table1: [ + { + sIndex: 1, + sType: '宸ュ湴', + sName: '涓婃捣鐢靛奖鑹烘湳鑱屼笟瀛﹂櫌鏂板缓閲戝北鏍″尯椤圭洰', + sLocation: '涓滆搐璺悍鍜岃矾', + sProblemList: [ + '1銆佹福鍦熷眬閮ㄦ湭瑕嗙洊', + '2銆佹暎璐х墿鏂欓湶澶╁爢鏀炬湭瑕嗙洊', + '3銆佸伐鍦板唴澶氭潯閬撹矾鏄庢樉娉ョ棔/娉ユ碁/绉皹/閬楁拻', + '4銆佸伐鍦板嚭鍏ュ彛100绫抽亾璺槑鏄剧Н灏�/閬楁拻/杞儙娉ュ嵃' + ], + sTown: '寮犲牥闀�', + sChange: '宸叉暣鏀�' + }, + { + sIndex: 2, + sType: '宸ュ湴', + sName: '涓婃捣浜ら�氬ぇ瀛﹀尰瀛﹂櫌闄勫睘鐟為噾鍖婚櫌閲戝北闄㈠尯椤圭洰', + sLocation: + '閲戝北鍖轰涵鏋楅晣36-05鍦板潡锛屼涵铏硅矾浠ヤ笢銆佹灄椤鸿矾浠ュ崡銆佹矆娴烽珮閫熶互瑗裤�佸ぇ浜叕璺互鍖�', + sProblemList: [ + '1銆佸澶栨湪鏉愬垏鍓茬瓑鏈ㄥ伐浣滀笟', + '2銆佸伐鍦板唴澶氭潯閬撹矾鏄庢樉娉ョ棔/娉ユ碁/绉皹/閬楁拻', + '3銆佹暎璐х墿鏂欓湶澶╁爢鏀炬湭瑕嗙洊', + '4銆佸ぇ闈㈢Н闇插ぉ瑁稿湡鏃犻槻灏樻帾鏂�' + ], + sTown: '浜灄闀�', + sChange: '宸叉暣鏀�' + }, + { + sIndex: 3, + sType: '宸ュ湴', + sName: '澶т俊.涓俊娴风洿鍗庝笢鏃犱汉鏈烘�婚儴鍩哄湴椤圭洰', + sLocation: '涓滆嚜鐒跺湴鍧楋紝瑗挎柊娉撅紝鍗楅粍鏂囨尘锛屽寳鑷劧鍦板潡', + sProblemList: ['1銆佸嚭鍏ュ彛杞﹁疆娉ョ棔', '2銆佷富閬撹矾娉ユ碁'], + sTown: '楂樻柊鍖�', + sChange: '宸叉暣鏀�' + } + ] +}; + +function export_doc() { + exportDocx( + '/绉嬪啲瀛g┖姘旇川閲忔敾鍧氬伐浣滄彁绀烘ā鏉�.docx', + param, + '宸ヤ綔鎻愮ず.docx' + ); +} +</script> diff --git a/src/views/fysp/check/components/ArbitraryPhoto.vue b/src/views/fysp/check/components/ArbitraryPhoto.vue index 058136a..f880324 100644 --- a/src/views/fysp/check/components/ArbitraryPhoto.vue +++ b/src/views/fysp/check/components/ArbitraryPhoto.vue @@ -27,14 +27,14 @@ v-for="item in typeList" :key="item.businesstypeid" :label=" - item.businesstype + ' (' + typeImgMap.get(activeId).length + ')' + item.businesstype + ' (' + typeImgMap.get(item.businesstypeid).length + ')' " :name="item.businesstypeid" > </el-tab-pane> </el-tabs> <el-empty v-if="isEmpty" description="鏆傛棤璁板綍" /> - <el-scrollbar class="imgs"> + <el-scrollbar v-else class="imgs"> <el-image v-for="(img, i) in typeImgMap.get(activeId)" :key="i" diff --git a/src/views/fysp/check/components/CompDevicePhono.vue b/src/views/fysp/check/components/CompDevicePhono.vue index 373e97e..d1871fe 100644 --- a/src/views/fysp/check/components/CompDevicePhono.vue +++ b/src/views/fysp/check/components/CompDevicePhono.vue @@ -29,7 +29,7 @@ <el-tab-pane v-for="item in typeList" :label="item.label" :name="item.id"> </el-tab-pane> </el-tabs> <el-empty v-if="imgObjList.length == 0" description="鏆傛棤璁板綍" /> - <div class="imgs"> + <el-scrollbar v-else class="imgs"> <el-image v-for="(img, i) in imgObjList" :class="[Boolean(img.isSelect) ? 'selected' : 'noActive', 'image']" @@ -38,7 +38,7 @@ lazy @click="onSelect(img, i)" /> - </div> + </el-scrollbar> </div> </div> </template> @@ -186,7 +186,7 @@ } */ .imgs { - height: 650px; + height: 50vh; width: 90%; min-height: 100px !important; /* border-style:solid; @@ -255,7 +255,8 @@ padding: 5px; } -.el-dialog__body { +::v-deep .el-dialog__body { height: 60vh; + padding: 10px calc(var(--el-dialog-padding-primary) + 10px) !important; } </style> diff --git a/src/views/fysp/check/components/CompDevicePhoto.vue b/src/views/fysp/check/components/CompDevicePhoto.vue new file mode 100644 index 0000000..94d2112 --- /dev/null +++ b/src/views/fysp/check/components/CompDevicePhoto.vue @@ -0,0 +1,53 @@ +<template> + <FYImageSelectDialog + :typeList="typeList" + :typeImgMap="typeImgMap" + :maxSelect="1" + ></FYImageSelectDialog> +</template> +<script setup> +import { ref, watch, computed } from 'vue'; + +const props = defineProps({ + // 灞曠ず妯″紡 + mode: { + type: Number, + default: 0 + }, + pics: Array +}); +// typeList: [ +// { id: 0, label: '鐩戞帶璁惧' }, +// { id: 1, label: '娌荤悊璁惧' }, +// { id: 2, label: '鐢熶骇璁惧' } +// ], +const typeList = computed(() => { + if (props.mode == 0) { + return [{ typeId: 0, typeName: '鐩戞帶璁惧' }]; + } else if (props.mode == 1) { + return [{ typeId: 1, typeName: '鏁存敼' }]; + } else { + return [{ typeId: 1, typeName: '鏈寚瀹�' }]; + } +}); +const typeImgMap = ref(new Map()); + +watch( + () => props.pics, + (nV, oV) => { + nV.forEach(e => { + if (!typeImgMap.value.has(e.topTypeId)) { + typeImgMap.value.set(e.topTypeId, []) + } + typeImgMap.value.get(r.topTypeId).push({}) + }); + typeImgMap.value.set( + 1, + nV.map((v) => { + return { url: v }; + }) + ); + }, + { immediate: true } +); +</script> \ No newline at end of file diff --git a/src/views/fysp/data-product/ProdDailyReport.vue b/src/views/fysp/data-product/ProdDailyReport.vue index ec520f7..510d10a 100644 --- a/src/views/fysp/data-product/ProdDailyReport.vue +++ b/src/views/fysp/data-product/ProdDailyReport.vue @@ -1,46 +1,55 @@ <template> <!-- 涓诲唴瀹� --> + <FYSearchBar ref="searchRef" @search="search" :loading="loading"> + <template #options> + <!-- 鍖哄幙 --> + <FYOptionLocation + :allOption="false" + :level="3" + :checkStrictly="false" + v-model:value="formSearch.locations" + style="width: 300px" + ></FYOptionLocation> + <!-- 鍦烘櫙绫诲瀷 --> + <!-- <FYOptionScene + :allOption="true" + :type="2" + v-model:value="formSearch.scenetype" + ></FYOptionScene> --> + <!-- 鏃堕棿 --> + <FYOptionTime + :initValue="false" + type="datetimerange" + v-model:value="formSearch.timeArray" + style="width: 250px" + ></FYOptionTime> + </template> + <template #buttons> + <el-button + icon="Download" + type="primary" + class="" + :loading="docLoading" + :disabled="!docParam" + @click="genWord()" + > + 鐢熸垚鎶ュ憡 + </el-button> + <el-button + icon="Download" + type="success" + class="" + :disabled="!docParam" + @click="exportToExcel()" + > + 涓嬭浇琛ㄦ牸 + </el-button> + </template> + </FYSearchBar> + <div class="m-task container"> <!--澶撮儴淇℃伅--> <div class="h-top col-md-12"> - <div class="options"> - <!-- <input type="date" class="c-time c-check" /> --> - <!-- 鏃堕棿 --> - <el-form-item label="鏃堕棿" :prop="prop" style="margin-left: 10px"> - <el-date-picker - v-model="formSearch.time" - type="date" - placeholder="閫夋嫨鏃堕棿" - start-placeholder="閫夋嫨寮�濮嬫椂闂�" - end-placeholder="閫夋嫨缁撴潫鏃堕棿" - style="width: 180px" - /> - </el-form-item> - <el-form-item label="鍖哄煙" :prop="prop" style="margin-left: 10px"> - <el-select - placeholder="Select" - v-model="formSearch.districtCode" - class="c-area c-check" - style="width: 100px" - > - <el-option label="閲戝北鍖�" value="310116"></el-option> - <el-option label="闈欏畨鍖�" value="310106"></el-option> - <el-option label="寰愭眹鍖�" value="310104"></el-option> - <el-option label="闀垮畞鍖�" value="310105"></el-option> - </el-select> - </el-form-item> - - <el-button - style="margin-left: 10px" - class="check-msg" - @click="search" - type="primary" - >鏌ヨ</el-button - > - <el-button type="primary" class="" @click="exportToExcel()"> - 鐢熸垚鎶ュ憡 - </el-button> - </div> <div class="m-top"> <span class="title-input"> {{ reportName }} </span> <!-- <input @@ -52,21 +61,10 @@ </div> <div class="m-msg col-md-12"> - <span - name="desc" - class="desc-textarea" - rows="5" - value="" - cols="" - disabled - ></span> + <span>{{ descMsg }}</span> <div class="report-table row"> <table id="table_subtask" class="" border="1"></table> </div> - </div> - - <div class="dark-screen"> - <i class="fa fa-spinner fa-spin fa-3x" style="color: white"></i> </div> </div> </template> @@ -77,28 +75,13 @@ import * as XLSX from 'xlsx'; import FileSaver from 'file-saver'; import analysisApi from '@/api/fysp/analysisApi.js'; +import { exportDocx } from '@/utils/doc'; + export default { name: 'DailyReport', computed: { reportName() { - var city = ''; - switch (this.formSearch.districtCode) { - case '310116': - city = '閲戝北鍖�'; - break; - case '310106': - city = '闈欏畨鍖�'; - break; - case '310104': - city = '寰愭眹鍖�'; - break; - case '310105': - city = '闀垮畞鍖�'; - break; - } - - let title = `${city}鎵皹姹℃煋杈呭姪鐩戠宸ヤ綔鏃ユ姤`; - return title; + return `${this.formSearch.locations.dName}鎵皹姹℃煋杈呭姪鐩戠宸ヤ綔鏃ユ姤`; } }, data() { @@ -235,10 +218,18 @@ headers: [], data: [] }, + loading: false, formSearch: { + locations: {}, + scenetype: {}, time: [], + timeArray: [new Date(), new Date()], districtCode: '310116' - } + }, + descMsg: '', + // 瀵煎嚭鎶ュ憡鍙傛暟 + docParam: undefined, + docLoading: false }; }, watch: { @@ -365,147 +356,98 @@ `${this.reportName}.xlsx` ); }, - downloadFile() { - // 鏂囦欢鏍囬 - let title = this.reportName; - // 琛ㄥご鎻忚堪 - let desc = document.querySelector('.desc-textarea').textContent; - // 鏃堕棿 - let time = document - .querySelector('.desc-textarea') - .textContent.split('锛�')[0]; - - // 鑾峰彇鏁版嵁 - let thData = Array.from(document.getElementsByTagName('th')).map( - (th) => th.innerText - ); - let tdData = Array.from(document.getElementsByTagName('td')).map( - (td) => td.innerText - ); - let totalList = []; - let subList = []; - let index = 2; - - let inputStatus = true; - for (let j = 0; j < thData.length; j++) { - subList.push(thData[j]); - } - totalList.push(subList); - subList = []; - - for (let i = 0; i < tdData.length; i++) { - if (tdData[i] !== String(index)) { - if (tdData[i] !== '') { - subList.push(tdData[i]); - } else { - if (inputStatus) { - let inputList = document.querySelectorAll(`.input-${subList[0]}`); - for (let j = 0; j < inputList.length; j++) { - subList.push(inputList[j].value); - } - inputStatus = false; - } else { - inputStatus = true; - } - } - } else { - totalList.push(subList); - subList = [String(index)]; - index += 1; - } - } - totalList.push(subList); - - // index: 0 head - // other: data - // title - - let fileData = { - title: title, - time: time, - desc: desc, - data: totalList - }; - - // if (fileData.title && fileData.time && fileData.desc && fileData.data.length) { - // fetch("http://47.100.191.150:9002/dustmonitor/report", { - // method: "POST", - // headers: { - // "Content-Type": "application/json" - // }, - // body: JSON.stringify(fileData) - // }) - // .then(response => response.json()) - // .then(res => { - // if (res.status === 200) { - // let name = res.name.split("./")[1]; - // setTimeout(() => { - // let a = document.createElement("a"); - // a.href = appConfig.downloadUrl + name; - // a.download = name; // 璁剧疆涓嬭浇鏂囦欢鍚� - // document.body.appendChild(a); - // a.click(); - // document.body.removeChild(a); - // }, 1000); - // } - // }) - // .catch(error => console.error("Error:", error)); - // } - }, search() { - let sTime = dayjs(this.formSearch.time).hour(0).minute(0).second(0); - let eTime = dayjs(this.formSearch.time).hour(23).minute(59).second(59); - eTime = eTime.toISOString(); - sTime = sTime.toISOString(); + let sTime = dayjs(this.formSearch.timeArray[0]) + .hour(0) + .minute(0) + .second(0) + .millisecond(0); + let eTime = dayjs(this.formSearch.timeArray[1]) + .hour(23) + .minute(59) + .second(59) + .millisecond(0); + // eTime = eTime.toISOString(); + // sTime = sTime.toISOString(); let config = { - startTime: sTime, - endTime: eTime, - districtCode: this.formSearch.districtCode + startTime: sTime.toDate(), + endTime: eTime.toDate(), + districtCode: this.formSearch.locations.dCode }; - analysisApi.checkProblem(config).then((res) => { - this.table.headers = res.tableTitle[0]; - this.table.data = res.tableContent; + this.loading = true; + analysisApi + .dailyreport(config) + .then((res) => { + this.table.headers = res.tableTitle[0]; + this.table.data = res.tableContent; - this.CompTable.init(res.tableTitle[0], res.tableContent); - this.CompTable.show('table_subtask'); + this.CompTable.init(res.tableTitle[0], res.tableContent); + this.CompTable.show('table_subtask'); - const countMap = new Map(); //鍚勫満鏅暟閲� - let proCount = 0; //鎬昏闂鏁伴噺 - let changeCount = 0; //鎬昏鏁存敼鏁伴噺 + const countMap = new Map(); //鍚勫満鏅暟閲� + let proCount = 0; //鎬昏闂鏁伴噺 + let changeCount = 0; //鎬昏鏁存敼鏁伴噺 + const tableRows = []; - res.tableContent.forEach((cList) => { - const sceneType = cList[2]; - if (!(sceneType in countMap)) { - countMap[sceneType] = 0; + res.tableContent.forEach((cList) => { + const sceneType = cList[2]; + if (!(sceneType in countMap)) { + countMap[sceneType] = 0; + } + countMap[sceneType] += 1; + proCount += Number(cList[10]); + changeCount += Number(cList[13]); + + tableRows.push({ + sIndex: cList[0], + sType: sceneType, + sName: cList[3], + sLocation: cList[4], + sProblemList: cList[8].split('\n'), + time: cList[6], + sTown: cList[5], + sChangeList: cList[11].split('\n') + }); + }); + + let countStr = ''; + for (const key in countMap) { + const e = countMap[key]; + if (countStr != '') { + countStr += '銆�'; + } + countStr += `${key}${e}涓猔; } - countMap[sceneType] += 1; - proCount += Number(cList[10]); - changeCount += Number(cList[13]); - }); + this.descMsg = `鍏卞贰鏌�${res.tableContent.length}涓壃灏樺満鏅紙${countStr}锛夛紝鍏卞彂鐜伴棶棰�${proCount}椤癸紝鐫d績鏁存敼浜�${changeCount}椤广�俙; - let countStr = ''; - for (const key in countMap) { - const e = countMap[key]; - if (countStr != '') { - countStr += '銆�'; - } - countStr += `${key}${e}涓猔; - } - - var descMsg = `鍏卞贰鏌�${res.tableContent.length}涓壃灏樺満鏅紙${countStr}锛夛紝鍏卞彂鐜伴棶棰�${proCount}椤癸紝鐫d績鏁存敼浜�${changeCount}椤癸紱鍓嶆湡浣欑暀闂鍧囧凡閿�椤广�俙; - console.log('descMsg', descMsg); - - // 鑾峰彇鎵�鏈夌被鍚嶄负 'desc-textarea' 鐨勫厓绱� - const textareas = document.querySelectorAll('.desc-textarea'); - - // 閬嶅巻杩欎簺鍏冪礌骞惰缃叾 HTML 鍐呭 - textareas.forEach(function (textarea) { - textarea.innerHTML = descMsg; - }); - // $('.desc-textarea').html(''); - // $('.desc-textarea').html(descMsg); - }); + this.docParam = { + month: sTime.month() + 1, + day: sTime.date(), + index: 1, + hasMoreDays: !sTime.isSame(eTime, 'day'), + endMonth: eTime.month() + 1, + endDay: eTime.date(), + totalScene: res.tableContent.length, + sceneNumTxt: countStr, + proNum: proCount, + changeNum: changeCount, + unChangeNum: proCount - changeCount, + table1: tableRows + }; + }) + .finally(() => (this.loading = false)); + }, + // 鐢熸垚word鎶ュ憡 + genWord() { + if (this.docParam) { + const param = this.docParam; + exportDocx( + '/绉嬪啲瀛g┖姘旇川閲忔敾鍧氬伐浣滄彁绀烘ā鏉�.docx', + param, + `绉嬪啲瀛g┖姘旇川閲忔敾鍧氬伐浣滄彁绀猴紙${param.month}鏈�${param.day}鏃ワ級.docx` + ); + } } } }; diff --git a/src/views/fysp/data-product/ProdSceneReport.vue b/src/views/fysp/data-product/ProdSceneReport.vue index 0e94a8d..1274d47 100644 --- a/src/views/fysp/data-product/ProdSceneReport.vue +++ b/src/views/fysp/data-product/ProdSceneReport.vue @@ -13,12 +13,13 @@ <template #main> <el-scrollbar class="el-scrollbar" v-loading="mainLoading"> <CompSceneConstructionInfo - title="A銆佸伐鍦板熀鏈俊鎭�" + title="A銆佸熀鏈俊鎭�" + :scene="formScene" :form-info="formSubScene" /> <div><el-text type="">闄勫浘鐗囷細</el-text></div> <CompImgInfo - title="鏂藉伐閾墝" + v-model:title="imgTitle" :img-src="sceneImg.url" @change="anyPhotoDialog = true" ></CompImgInfo> @@ -29,9 +30,9 @@ v-for="(item, i) in deviceList" :key="i" down-title - :title="item._deviceTypeName" + v-model:title="item._deviceTypeName" :img-src="item._showStatusPic" - @change="showDevicePhotoDialog(item)" + @change="showDevicePhotoDialog(item, i)" ></CompImgInfo> </el-space> <el-divider /> @@ -41,10 +42,32 @@ v-for="(item, i) in curProList" :key="i" :problem="item" + @change="(value) => handleProPicSelect(value, i)" ></CompProblemTable> </el-space> + <el-divider /> <el-text tag="h1">D銆佹壃灏樻薄鏌撻槻娌诲缓璁�</el-text> - + <div class="p-b-8"> + 閽堝璇ュ伐鍦版湰鏈熷贰鏌ュ彂鐜扮殑闂锛岃瘎浼颁负鎵皹姹℃煋闃叉不 + <el-radio-group v-model="radioStandard" size="default"> + <el-radio value="瑙勮寖" border>瑙勮寖</el-radio> + <el-radio value="鍩烘湰瑙勮寖" border>鍩烘湰瑙勮寖</el-radio> + <el-radio value="涓嶈鑼�" border>涓嶈鑼�</el-radio> + <el-radio value="涓ラ噸涓嶈鑼�" border>涓ラ噸涓嶈鑼�</el-radio> + </el-radio-group> + 宸ュ湴锛屽缓璁宸ュ湴涓ユ牸鎸夌収銆婃壃灏橀槻娌绘柟妗堛�嬨�併�婃壃灏橀槻娌绘壙璇轰功銆嬨�併�婃枃鏄庢柦宸ョ鐞嗚鑼冦�嬨�併�婄簿缁嗗寲绠$悊鎸囨爣銆嬬瓑鐩稿叧鏂囦欢钀藉疄鏁存敼銆� + </div> + <el-row justify="center" style="height: 200px"> + <el-button + icon="Download" + type="primary" + :loading="docLoading" + :disabled="!sceneImg.url" + @click="genWord()" + > + 鐢熸垚鎶ュ憡 + </el-button> + </el-row> </el-scrollbar> </template> </BaseContentLayout> @@ -83,14 +106,18 @@ import taskApi from '@/api/fysp/taskApi'; import sceneApi from '@/api/fysp/sceneApi'; import deviceApi from '@/api/fysp/deviceApi'; +import evaluateApi from '@/api/fysp/evaluateApi'; import { formatDeviceList } from '@/model/fysp/device'; import { enumDevice, toLabel } from '@/enum/device/device'; +import { exportDocx } from '@/utils/doc'; +import right_triangle from '@/assets/image/right_triangle.png'; import CompSceneConstructionInfo from '@/views/fysp/scene/CompSceneConstructionInfo.vue'; import ArbitraryPhoto from '@/views/fysp/check/components/ArbitraryPhoto.vue'; import CompDevicePhono from '@/views/fysp/check/components/CompDevicePhono.vue'; import CompImgInfo from '@/views/fysp/data-product/components/CompImgInfo.vue'; import CompProblemTable from './components/CompProblemTable.vue'; +import dayjs from 'dayjs'; /************************* 宸︿晶宸℃煡浠诲姟閫夊崟 **********************************/ const curSubtask = ref({}); @@ -151,16 +178,19 @@ }); fetchDeviceList(s); fetchProblems(s); + fetchEvaluation(s); } /************************* 鍦烘櫙鍩烘湰淇℃伅 **********************************/ +const imgTitle = ref('鏂藉伐閾墝'); +const formScene = ref({}); const formSubScene = ref({}); function fetchSceneInfo(sceneId) { formSubScene.value = {}; sceneImg.value = {}; return sceneApi.getSceneDetail(sceneId).then((res) => { //鍦烘櫙 - // if (res.data.scense) formScene = res.data.scense; + if (res.data.scense) formScene.value = res.data.scense; formSubScene.value = res.data.subScene ? res.data.subScene : {}; // if (res.data.sceneDevice) { // formSceneDevice = res.data.sceneDevice; @@ -185,12 +215,13 @@ // 璁惧鍥剧墖閫夋嫨瀵硅瘽妗� const deiveceImgDialog = ref(false); -const showDeviceImg = ref({}); +const showDeviceIndex = ref(0); const showDeviceImgList = ref([]); // 璁惧鍥剧墖鍒楄〃 const deviceList = ref([]); -function showDevicePhotoDialog(device) { +function showDevicePhotoDialog(device, index) { + showDeviceIndex.value = index; deiveceImgDialog.value = true; showDeviceImgList.value = []; let imgList = []; @@ -206,7 +237,7 @@ }) ); }); - console.log(imgList); + // console.log(imgList); showDeviceImgList.value = imgList; } @@ -214,7 +245,7 @@ function handleSelectDevicePhoto(data) { deiveceImgDialog.value = false; if (data.length > 0) { - showDeviceImg.value = { url: data[0].url }; + deviceList.value[showDeviceIndex.value]._showStatusPic = data[0]._picUrl; } } @@ -271,14 +302,119 @@ } } /************************* 鐜板満宸℃煡鎯呭喌锛堥棶棰樹笌鏁存敼锛� **********************************/ + +const problemDesc = ref(''); //褰撳墠浠诲姟鐨勯棶棰樺垪琛� const curProList = ref([]); +const month = ref(''); +const selectedProList = ref([]); function fetchProblems(s) { curProList.value = []; taskApi.getProBySubtask(s.data.stGuid).then((res) => { curProList.value = res; + + // 鐢熸垚宸℃煡鎻忚堪鏂囨湰 + month.value = dayjs(s.data.stPlanTime).month() + 1; + const proCount = curProList.value.length; + problemDesc.value = `${month.value}鏈堝贰鏌ュ叡璁″彂鐜�${proCount}涓棶棰榒; + if (proCount > 0) { + problemDesc.value += '锛�'; + curProList.value.forEach((p, i) => { + problemDesc.value += `${i + 1}銆�${p.problemname}锛沗; + }); + problemDesc.value += '濡備笅鍥炬墍绀猴細'; + } else { + problemDesc.value += '銆�'; + } + + // 鐢熸垚閫変腑鐨勯棶棰樺拰鏁存敼鍥剧墖鎻忚堪 + selectedProList.value = curProList.value.map((v) => { + return {}; + }); }); } + +function handleProPicSelect(value, index) { + selectedProList.value[index] = value; +} /************************* 鎵皹闃叉不寤鸿 **********************************/ +const radioStandard = ref('瑙勮寖'); +function fetchEvaluation(s) { + evaluateApi.fetchItemEvaluation(s.data.stGuid).then((res) => { + radioStandard.value = res.data.grade; + }); +} + +/************************* 鐢熸垚鎶ュ憡 **********************************/ + +const docLoading = ref(false); +// 鐢熸垚word鎶ュ憡 +function genWord() { + const _deviceList = []; + for (let i = 0; i < deviceList.value.length; i += 2) { + const d1 = deviceList.value[i]; + const d2 = + i + 1 < deviceList.value.length ? deviceList.value[i + 1] : undefined; + _deviceList.push({ + _showStatusPic_1: d1._showStatusPic, + _deviceTypeName_1: d1._deviceTypeName, + // hasPic2: d2 ? true : false, + _showStatusPic_2: d2 ? d2._showStatusPic : right_triangle, + _deviceTypeName_2: d2 ? d2._deviceTypeName : '' + }); + } + const param = { + index: formScene.value.index, + sceneName: formScene.value.name, + projectType: formSubScene.value.csProjectType, + stage: formSubScene.value.siExtension1, + startTime: formSubScene.value.csStartTime, + endTime: formSubScene.value.csEndTime, + leftTime: formSubScene.value.csLeftTime, + location: formScene.value.location, + floorSpace: formSubScene.value.csFloorSpace, + constructionArea: formSubScene.value.csConstructionArea, + constructionAreaPerMonth: formSubScene.value.csConstructionAreaPerMonth, + contacts: formScene.value.contacts, + contactst: formScene.value.contactst, + securityOfficer: formSubScene.value.csSecurityOfficer, + securityOfficerTel: formSubScene.value.csSecurityOfficerTel, + constructionUnit: formSubScene.value.csConstructionUnit, + employerUnit: formSubScene.value.csEmployerUnit, + sceneType: formScene.value.type, + imgTitle: imgTitle.value, + imgTitle_url: sceneImg.value.url, + deviceList: _deviceList, + problemDesc: problemDesc.value, + problemList: selectedProList.value.map((v) => { + return { + month: month.value, + ...v + }; + }), + standard_1: radioStandard.value == '瑙勮寖', + standard_2: radioStandard.value == '鍩烘湰瑙勮寖', + standard_3: radioStandard.value == '涓嶈鑼�', + standard_4: radioStandard.value == '涓ラ噸瑙勮寖' + }; + for (const key in param) { + if (param[key] == undefined) { + param[key] = ''; + } + } + const date = dayjs(curSubtask.value.data.stPlanTime).format('MM鏈圖D鏃�'); + console.log(param); + + docLoading.value = true; + exportDocx( + '/鍗曚綋妯$増.docx', + param, + `${param.sceneName}鍗曚綋锛�${date}锛�.docx`, + { + horizontalHeight: 368, + verticalWidth: 266 + } + ).finally(() => (docLoading.value = false)); +} </script> diff --git a/src/views/fysp/data-product/components/CompImgInfo.vue b/src/views/fysp/data-product/components/CompImgInfo.vue index 5afab32..48a0b51 100644 --- a/src/views/fysp/data-product/components/CompImgInfo.vue +++ b/src/views/fysp/data-product/components/CompImgInfo.vue @@ -4,15 +4,19 @@ <tr v-if="!downTitle"> <td> <el-row justify="space-between" align="middle"> - {{ title }} - <el-button size="small" @click="$emit('change')">{{ - btnName - }}</el-button> + <!-- {{ title }} --> + <el-input + size="small" + :model-value="title" + @input="handleInputChange" + placeholder="鏍囬" + style="width: 150px" + /> </el-row> </td> </tr> <tr> - <td> + <td style="position: relative"> <el-image class="image" :src="imgSrc" @@ -29,15 +33,22 @@ </div> </template> </el-image> + <el-button class="pop-button" size="small" @click="$emit('change')">{{ + btnName + }}</el-button> </td> </tr> <tr v-if="downTitle"> <td> <el-row justify="space-between" align="middle"> - {{ title }} - <el-button size="small" @click="$emit('change')">{{ - btnName - }}</el-button> + <!-- {{ title }} --> + <el-input + size="small" + :model-value="title" + @input="handleInputChange" + placeholder="鏍囬" + style="width: 150px" + /> </el-row> </td> </tr> @@ -60,7 +71,11 @@ // const unchangeImg = '../../../../assets/image/unchange.png' -const emit = defineEmits(['change']); +const emit = defineEmits(['change', 'update:title']); + +function handleInputChange(value) { + emit('update:title', value); +} </script> <style scoped> .image { @@ -96,4 +111,10 @@ height: 100%; background: var(--el-fill-color-light); } + +.pop-button { + position: absolute; + bottom: 0; + right: 0; +} </style> diff --git a/src/views/fysp/data-product/components/CompProblemTable.vue b/src/views/fysp/data-product/components/CompProblemTable.vue index 3f145ce..0d6d3d8 100644 --- a/src/views/fysp/data-product/components/CompProblemTable.vue +++ b/src/views/fysp/data-product/components/CompProblemTable.vue @@ -74,6 +74,7 @@ </table> <CompProblemPicSelect v-if="pics.length > 0" + title="闂鍥剧墖" v-model:dialog-visible="proDialog" mode="problem" :pics="pics[0].path" @@ -82,6 +83,7 @@ ></CompProblemPicSelect> <CompProblemPicSelect v-if="pics.length > 1" + title="鏁存敼鍥剧墖" v-model:dialog-visible="changeDialog" mode="change" :pics="pics[1].path" @@ -138,13 +140,26 @@ function handleProPicSelect(imgList) { if (imgList && imgList.length > 0) { seletcedProblemPic.value = imgList[0].url; + onChange(); } } function handleChangePicSelect(imgList) { if (imgList && imgList.length > 0) { seletcedChangePic.value = imgList[0].url; + onChange(); } +} + +function onChange() { + const value = { + proPic: seletcedProblemPic.value, + changePic: seletcedChangePic.value ? seletcedChangePic.value : unchangeImg, + location: props.problem.location, + problemDes, + changeDes + }; + emit('change', value); } watch( @@ -154,10 +169,23 @@ getPics(); problemDes.value = nV.problemname; changeDes.value = nV.ischanged ? '宸叉暣鏀�' : '鏈暣鏀�'; + + onChange(); } }, { immediate: true } ); + +watch(problemDes, (nV, oV) => { + if (nV != oV) { + onChange(); + } +}); +watch(changeDes, (nV, oV) => { + if (nV != oV) { + onChange(); + } +}); </script> <style scoped> .image { diff --git a/src/views/fysp/scene/CompSceneConstructionInfo.vue b/src/views/fysp/scene/CompSceneConstructionInfo.vue index 6d2c70f..65d98bd 100644 --- a/src/views/fysp/scene/CompSceneConstructionInfo.vue +++ b/src/views/fysp/scene/CompSceneConstructionInfo.vue @@ -1,7 +1,7 @@ <!-- 宸ュ湴涓撳睘淇℃伅缂栬緫 --> <template> <el-form - v-if="showStyle == 'form'" + v-show="showStyle == 'form'" :inline="false" :model="formObj" ref="formRef" @@ -164,7 +164,7 @@ </el-form> <el-descriptions - v-else-if="showStyle == 'descriptions'" + v-show="showStyle == 'descriptions'" :column="2" :size="fontSize" direction="horizontal" @@ -175,14 +175,17 @@ </template> <template #extra> <el-button + :disabled="!edit && !ignoreEdit" :size="fontSize" - :disabled="!edit" type="primary" @click="onSubmit" :loading="loading" >鎻愪氦</el-button > - <el-button :size="fontSize" :disabled="!edit" @click="onReset" + <el-button + :size="fontSize" + :disabled="!edit && !ignoreEdit" + @click="onReset" >閲嶇疆</el-button > </template> @@ -237,7 +240,7 @@ <el-descriptions-item label="鏂藉伐鍦板潃" span="2" ><el-input clearable - v-model="formObj.location" + v-model="sceneObj.location" placeholder="鏂藉伐鍦板潃" :size="fontSize" /></el-descriptions-item> @@ -271,6 +274,25 @@ <template #append>銕�</template> </el-input></el-descriptions-item > + <el-descriptions-item label="椤圭洰璐熻矗浜�" + ><el-input + :size="fontSize" + clearable + v-model="sceneObj.contacts" + placeholder="椤圭洰璐熻矗浜�" + /></el-descriptions-item> + <el-descriptions-item label="椤圭洰璐熻矗浜虹數璇�" + ><el-input + :size="fontSize" + clearable + type="tel" + v-model="sceneObj.contactst" + placeholder="椤圭洰璐熻矗浜虹數璇�" + > + <template #prepend> + <el-icon><Iphone /></el-icon> + </template> </el-input + ></el-descriptions-item> <el-descriptions-item label="瀹夊叏鍛�" ><el-input :size="fontSize" @@ -342,7 +364,7 @@ </template> <script setup> -import { defineProps, defineEmits, reactive, ref, watch } from 'vue'; +import { reactive, ref, watch, computed } from 'vue'; import { useDateFormat } from '@vueuse/core'; import { enumStatusNA, enumStageNA } from '@/enum/construction'; import sceneApi from '@/api/fysp/sceneApi'; @@ -366,8 +388,14 @@ title: String }); const fontSize = ref('small'); -const emit = defineEmits(['onSubmit', 'onCancel']); +const emit = defineEmits([ + 'onSubmit', + 'onCancel', + 'update:scene', + 'update:formInfo' +]); +const sceneObj = ref({}); const { formObj, formRef, edit, onSubmit, onReset } = useFormConfirm({ submit: { do: submit @@ -376,6 +404,8 @@ do: cancel } }); +const ignoreEdit = computed(() => props.showStyle == 'descriptions'); + const loading = ref(false); const status = reactive(enumStatusNA()); const stage = reactive(enumStageNA()); @@ -404,7 +434,7 @@ }); // 鍒涘缓鎴栨洿鏂板満鏅鎯� -function createOrupdateScene() { +function createOrupdateSubScene() { loading.value = true; if (formObj.value._timeRange && formObj.value._timeRange.length == 2) { @@ -415,6 +445,8 @@ return sceneApi .updateSubScene(props.sceneType, formObj.value) .then((res) => { + emit('onSubmit', formObj); + emit('update:formInfo', formObj); return res.data; }) .finally(() => { @@ -422,10 +454,16 @@ }); } -function submit() { - emit('onSubmit', formObj); +// 鏇存柊鍦烘櫙 +function updateScene() { + return sceneApi.updateScene(sceneObj.value).then(() => { + emit('update:scene', sceneObj); + }); +} - return createOrupdateScene(); +function submit() { + updateScene(); + return createOrupdateSubScene(); } function cancel() { @@ -445,6 +483,16 @@ }, { deep: false, immediate: true } ); + +watch( + () => props.scene, + (nValue) => { + if (nValue) { + sceneObj.value = nValue; + } + }, + { deep: false, immediate: true } +); </script> <style> -- Gitblit v1.9.3