From 58c0f11fe2f23a1be2dec768f9ac02107301a634 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期五, 19 九月 2025 17:30:36 +0800 Subject: [PATCH] 2025.9.19 数据产品(待完成) --- src/views/fysp/data-product/base-data-product/ProdMonitorDataInfo.vue | 98 +++++ src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue | 40 + src/components/search-option/FYOptionTopTask.vue | 84 ++++ src/views/fysp/data-product/components/ProdQueryOpt.vue | 0 src/components.d.ts | 2 src/constants/menu.js | 5 src/router/index copy.js | 4 src/components/search-option/FYOptionLocation.vue | 2 src/views/fysp/data-product/ProdLawEnforceList.vue | 14 src/views/fysp/data-product/components/ProdQueryOptCompare.vue | 102 +++++ src/utils/echart-util.js | 208 ++++------ src/views/fysp/data-product/middle-data-product/ProdEvaluationSummary.vue | 28 + src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue | 33 + src/views/fysp/data-product/components/BaseProdProcess.vue | 4 src/views/fysp/data-product/components/CompProdManage.vue | 50 +- src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue | 7 src/views/fysp/data-product/components/ProdDownload.vue | 0 src/views/fysp/data-product/middle-data-product/ProdProblemTypeSummary.vue | 127 ++++++ src/views/fysp/data-product/middle-data-product/ProdMonitorDeviceSummary.vue | 28 + src/views/fysp/data-product/base-data-product/ManageBaseProd.vue | 27 + src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue | 2 src/router/index.js | 83 +++ src/components/table/FYTable.vue | 8 src/main.js | 4 src/views/fysp/data-product/middle-data-product/ProdInspectionSummary.vue | 75 +++ src/views/fysp/support/JingAnNightConstruction.vue | 24 + src/utils/excel.js | 4 src/views/fysp/data-product/middle-data-product/ManageMiddleProd.vue | 31 + src/views/fysp/data-product/components/CompProdTextGenerator.vue | 25 + 29 files changed, 927 insertions(+), 192 deletions(-) diff --git a/src/components.d.ts b/src/components.d.ts index 3d570e1..61329ff 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -13,6 +13,7 @@ CompGenericWrapper: typeof import('./components/CompGenericWrapper.vue')['default'] CompQuickSet: typeof import('./components/search-option/CompQuickSet.vue')['default'] Content: typeof import('./components/core/Content.vue')['default'] + copy: typeof import('./components/search-option/FYOptionScene copy.vue')['default'] ElAffix: typeof import('element-plus/es')['ElAffix'] ElAside: typeof import('element-plus/es')['ElAside'] ElAvatar: typeof import('element-plus/es')['ElAvatar'] @@ -92,6 +93,7 @@ FYOptionSupervisionStatus: typeof import('./components/search-option/FYOptionSupervisionStatus.vue')['default'] FYOptionText: typeof import('./components/search-option/base/FYOptionText.vue')['default'] FYOptionTime: typeof import('./components/search-option/FYOptionTime.vue')['default'] + FYOptionTopTask: typeof import('./components/search-option/FYOptionTopTask.vue')['default'] FYOptionUserType: typeof import('./components/search-option/FYOptionUserType.vue')['default'] FYPageHeader: typeof import('./components/head/FYPageHeader.vue')['default'] FYReconfrimButton: typeof import('./components/button/FYReconfrimButton.vue')['default'] diff --git a/src/components/search-option/FYOptionLocation.vue b/src/components/search-option/FYOptionLocation.vue index cf5cee9..3a0aabb 100644 --- a/src/components/search-option/FYOptionLocation.vue +++ b/src/components/search-option/FYOptionLocation.vue @@ -1,13 +1,13 @@ <template> <el-form-item :label="placeholder" :prop="prop"> <el-cascader + v-bind="$attrs" :model-value="formatedValue" @change="handleChange" :options="locations" :placeholder="placeholder" :props="optionProps" style="width: 320px" - v-bind="$attrs" /> </el-form-item> </template> diff --git a/src/components/search-option/FYOptionTopTask.vue b/src/components/search-option/FYOptionTopTask.vue new file mode 100644 index 0000000..291094b --- /dev/null +++ b/src/components/search-option/FYOptionTopTask.vue @@ -0,0 +1,84 @@ +<template> + <el-form-item :label="label" :prop="prop"> + <el-select + :model-value="formatedValue" + @update:model-value="handleChange" + placeholder="鎬讳换鍔�" + style="width: 260px" + > + <el-option + v-for="s in topTasks" + :key="s.value" + :label="s.label" + :value="s.value" + /> + </el-select> + </el-form-item> +</template> + +<script> +import taskApi from '@/api/fysp/taskApi'; + +export default { + props: { + label: { + type: String, + default: '鎬讳换鍔�' + }, + // 杩斿洖缁撴灉 + value: Object, + // 鏄惁榛樿杩斿洖鍒濆閫夐」 + initValue: { + type: Boolean, + default: true + }, + // form琛ㄥ崟缁戝畾灞炴�у悕 + prop: { + type: String, + default: 'topTaskId' + }, + }, + emits: ['update:value'], + data() { + return { + selected: {}, + topTasks: [], + }; + }, + computed: { + formatedValue() { + return this.value.tguid; + } + }, + methods: { + //鑾峰彇鏌ヨ鏉′欢 + getOptions() { + taskApi.getTopTask().then((res) => { + const list = res.map((r) => { + return { + value: r.tguid, + label: r.name, + data: r + }; + }); + this.topTasks = list; + if (this.initValue) { + this.handleChange(list[0].value); + } + }); + }, + //鏌ヨ瀛愪换鍔$粺璁′俊鎭� + handleChange(value) { + const task = this.topTasks.find( + (t) => t.data.tguid == value + ); + const param = task ? task.data : {} + + this.$emit('update:value', param); + }, + }, + mounted() { + this.getOptions(); + } +}; +</script> diff --git a/src/components/table/FYTable.vue b/src/components/table/FYTable.vue index a85de22..2590983 100644 --- a/src/components/table/FYTable.vue +++ b/src/components/table/FYTable.vue @@ -90,6 +90,10 @@ type: Number, default: 0 }, + defaultPageSize: { + type: Number, + default: 20 + }, // 棰濆鐨勯珮搴︼紝鐢ㄤ簬璁$畻琛ㄦ牸楂樺害 extraHeight: { type: Number, @@ -102,7 +106,7 @@ tableData: [], total: 0, currentPage: 1, - pageSize: 20, + pageSize: this.defaultPageSize, loading: false, fontSize: 'default' }; @@ -142,7 +146,7 @@ if (nValue != oValue) { this.tableHeight = this.calcTableHeight(); } - }, + } } }, computed: {}, diff --git a/src/constants/menu.js b/src/constants/menu.js index 767b029..136fcc1 100644 --- a/src/constants/menu.js +++ b/src/constants/menu.js @@ -74,6 +74,11 @@ name: '涓棿鏁版嵁浜у搧', children: [ { + path: '/fysp/data-product/middle/home/inspectionSummary', + icon: 'Document', + name: '鏈堝害宸℃煡绠�鎶�' + }, + { path: '/fysp/data-product/profollow', icon: 'Document', name: '闂鍔ㄦ�佽窡韪�' diff --git a/src/main.js b/src/main.js index ceb52d6..175bb60 100644 --- a/src/main.js +++ b/src/main.js @@ -20,9 +20,6 @@ import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'; import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'; -// echarts -import * as echarts from 'echarts' - dayjs.extend(isSameOrAfter); dayjs.extend(isSameOrBefore); @@ -30,7 +27,6 @@ const app = createApp(App); app.config.globalProperties.$fm = timeUtil; -app.config.globalProperties.$echarts = echarts app.config.globalProperties.$message = ElMessage app.config.globalProperties.$notification = ElNotification app.config.globalProperties.$messageBox = ElMessageBox diff --git a/src/router/index copy.js b/src/router/index copy.js index fa7bcf8..2ff6cb5 100644 --- a/src/router/index copy.js +++ b/src/router/index copy.js @@ -181,10 +181,10 @@ }, { // 鍩虹浜у搧-绠$悊 - name: 'ProdManage', + name: 'ManageBaseProd', path: 'fysp/data-product/base/home', component: () => - import('@/views/fysp/data-product/base-data-product/ProdManage.vue'), + import('@/views/fysp/data-product/base-data-product/ManageBaseProd.vue'), children: [ { // 鍩虹浜у搧-鍦烘櫙娓呭崟 diff --git a/src/router/index.js b/src/router/index.js index c229675..ba8f36f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -70,7 +70,7 @@ import('@/views/fysp/data-product/ProdSceneReport.vue') }, { - //鍦烘櫙鎶ュ憡 + //鑱斿悎鎵ф硶娓呭崟 name: 'lawenforcelist', path: 'lawenforcelist', component: () => @@ -82,18 +82,18 @@ children: [ { // 鍩虹浜у搧-绠$悊 - name: 'ProdManage', + name: 'ManageBaseProd', path: 'home', component: () => import( - '@/views/fysp/data-product/base-data-product/ProdManage.vue' + '@/views/fysp/data-product/base-data-product/ManageBaseProd.vue' ), children: [ { // 鍩虹浜у搧-鍦烘櫙娓呭崟 path: 'scene', name: 'ProdSceneInfo', - meta: { keepAlive: true, key: 'ProdManage' }, + meta: { keepAlive: false, key: 'ManageBaseProd' }, component: () => import( '@/views/fysp/data-product/base-data-product/ProdSceneInfo.vue' @@ -103,17 +103,17 @@ // 鍩虹浜у搧-瑙勮寖鎬ц瘎浼� path: 'evaluate', name: 'ProdEvaluationInfo', - meta: { keepAlive: true, key: 'ProdManage' }, + meta: { keepAlive: false, key: 'ManageBaseProd' }, component: () => import( '@/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue' ) }, { - // 鍩虹浜у搧-宸℃煡淇℃伅 + // 鍩虹浜у搧-鏁存敼娓呭崟 path: 'inspection', name: 'ProdInspectionInfo', - meta: { keepAlive: true, key: 'ProdManage' }, + meta: { keepAlive: false, key: 'ManageBaseProd' }, component: () => import( '@/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue' @@ -123,7 +123,7 @@ // 鍩虹浜у搧-鐩戞祴鏁版嵁 path: 'monitordata', name: 'ProdMonitorDataInfo', - meta: { keepAlive: true, key: 'ProdManage' }, + meta: { keepAlive: false, key: 'ManageBaseProd' }, component: () => import( '@/views/fysp/data-product/base-data-product/ProdMonitorDataInfo.vue' @@ -141,6 +141,73 @@ ) } ] + }, + { + name: 'dataProdMiddle', + path: 'middle', + children: [ + { + // 涓棿浜у搧-绠$悊 + name: 'ManageMiddleProd', + path: 'home', + component: () => + import( + '@/views/fysp/data-product/middle-data-product/ManageMiddleProd.vue' + ), + children: [ + { + // 涓棿浜у搧-鏈堝害宸℃煡鎯呭喌姹囨�� + path: 'inspectionSummary', + name: 'ProdInspectionSummary', + meta: { keepAlive: false, key: 'ManageMiddleProd' }, + component: () => + import( + '@/views/fysp/data-product/middle-data-product/ProdInspectionSummary.vue' + ) + }, + { + // 涓棿浜у搧-鏈堝害闂姹囨�� + path: 'problemTypeSummary', + name: 'ProdProblemTypeSummary', + meta: { keepAlive: false, key: 'ManageMiddleProd' }, + component: () => + import( + '@/views/fysp/data-product/middle-data-product/ProdProblemTypeSummary.vue' + ) + }, + { + // 涓棿浜у搧-鍒嗚闀囧崟鍦烘櫙闂鏁板潎鍊� + path: 'problemCountSummary', + name: 'ProdProblemCountSummary', + meta: { keepAlive: false, key: 'ManageMiddleProd' }, + component: () => + import( + '@/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue' + ) + }, + { + // 涓棿浜у搧-鐩戞祴璁惧姹囨�� + path: 'monitorDeviceSummary', + name: 'ProdMonitorDeviceSummary', + meta: { keepAlive: false, key: 'ManageMiddleProd' }, + component: () => + import( + '@/views/fysp/data-product/middle-data-product/ProdMonitorDeviceSummary.vue' + ) + }, + { + // 涓棿浜у搧-璇勪及鎯呭喌 + path: 'evaluationSummary', + name: 'ProdEvaluationSummary', + meta: { keepAlive: false, key: 'ManageMiddleProd' }, + component: () => + import( + '@/views/fysp/data-product/middle-data-product/ProdEvaluationSummary.vue' + ) + }, + ] + }, + ] } ] }, diff --git a/src/utils/echart-util.js b/src/utils/echart-util.js index 0934d69..ad12e65 100644 --- a/src/utils/echart-util.js +++ b/src/utils/echart-util.js @@ -1,123 +1,95 @@ -// 閫掑綊鐨勮幏鍙杘bj涓殑prop灞炴�� 瑙e喅鏈夋椂闇�瑕佸彇val.obj.prop鐨勬儏鍐� -function getPropValueLoop(obj, prop) { - if (typeof prop !== 'string') { - return obj; - } - const props = prop.split('.'); - let result = obj; - props.forEach((item) => { - result = result[item]; - }); - return result; -} -function getCount(array, element) { - let count = 0; - array.forEach((e) => { - if (e == element) { - count++; - } - }); - return count; -} -export default { - /** 灏哻hart鍥捐〃杞寲涓哄浘鐗噓rl - * @param chart锛� chart鍥捐〃鐨勫疄渚� - * */ - chartToImageUrl(chart) { - const dataURL = chart.getDataURL({ - pixelRatio: 5, // 鎻愰珮鍥剧墖璐ㄩ噺 - backgroundColor: '#FFFFFF', // 璁剧疆鑳屾櫙棰滆壊 - excludeComponents: ['toolbox'], // 鎺掗櫎宸ュ叿绠辩粍浠� - type: 'png' // 杈撳嚭鍥剧墖绫诲瀷涓篜NG - }); - return dataURL; - }, - // 灞曠ず data 鏁扮粍涓璞$殑 prop 灞炴�х殑楗煎浘, title 鏄ゼ鍥剧殑鏍囬 - getPieChartByDataAndProp(data, prop, label) { - let chartData = []; - function hasThisName(name) { - for (let index = 0; index < chartData.length; index++) { - const element = chartData[index]; - if (element.name === name) { - return true; +function pieChartOption() { + return { + color: [ + '#5470c6', + '#91cc75', + '#fac858', + '#ee6666', + '#73c0de', + '#3ba272', + '#fc8452', + '#9a60b4', + '#ea7ccc', + '#514a9d', + '#2ec7c9', + '#b6a2de' + ], + title: { + text: `楗煎浘榛樿鍚嶇О`, + left: 'center' // 鏍囬灞呬腑鏄剧ず + }, + // 娣诲姞宸ュ叿鏍忛厤缃紝鍖呭惈涓嬭浇鍔熻兘 + toolbox: { + show: true, + feature: { + saveAsImage: { + show: true, + title: '涓嬭浇鍥捐〃', + type: 'png', + pixelRatio: 2 // 鎻愰珮鍥剧墖娓呮櫚搴� } } - return false; - } - - data.map((item) => { - const name = getPropValueLoop(item, prop); - if (hasThisName(name)) { - chartData.map((item) => { - if (item.name === name) { - item.value++; + }, + tooltip: { + trigger: 'item', // 楗煎浘浣跨敤item瑙﹀彂tooltip + formatter: '{a} <br/>{b}: {c} ({d}%)' // 鏄剧ず鏍煎紡锛氬悕绉�: 鏁伴噺 (鐧惧垎姣�) + }, + legend: { + show: false, + orient: 'vertical', + left: 'right', // 鍥句緥灞呭乏鍨傜洿鎺掑垪 + data: ['sample1', 'sample2', 'sample3'] // 鍥句緥鏁版嵁涓洪棶棰樼被鍨嬪悕绉� + }, + series: [ + { + name: 'sample', + type: 'pie', // 鍥捐〃绫诲瀷鏀逛负楗煎浘 + radius: '60%', // 楗煎浘鍗婂緞 + center: ['50%', '55%'], // 楗煎浘涓績浣嶇疆 + data: [ + { + name: 'sample1', + value: 100 + }, + { + name: 'sample2', + value: 200 + }, + { + name: 'sample3', + value: 300 } - }); - } else { - chartData.push({ - name: name, - value: 1 - }); + ], + label: { + show: true, + formatter: '{b}: {c} ({d}%)' // 鎵囧尯鏍囩鏄剧ず锛氬悕绉�: 鏁伴噺 (鐧惧垎姣�) + } } - }); + ] + }; +} - return { - title: { - text: label, - left: 'center' - }, - tooltip: { - trigger: 'item' - }, - legend: { - orient: 'vertical', - left: 'left' - }, - series: [ - { - type: 'pie', - radius: '50%', - data: chartData, - emphasis: { - itemStyle: { - shadowBlur: 10, - shadowOffsetX: 0, - shadowColor: 'rgba(0, 0, 0, 0.5)' - } - } - } - ] - }; - }, - // 灞曠ず data 鏁扮粍涓璞$殑 prop 灞炴�х殑鐩存柟鍥�, title 鏄洿鏂瑰浘鐨勬爣棰� - getBarChartByDataAndProp(data, prop, title) { - let series = data.map((item) => getPropValueLoop(item, prop)); - const option = { - title: { - text: title //璁剧疆鏍囬 - }, - xAxis: { - type: 'category', - data: Array.from(new Set(series)), - axisLabel: { - rotate: 45, // 鏃嬭浆鏍囩锛岄伩鍏嶉噸鍙� - // 鎴栬�� - interval: 0 // 鏄剧ず鎵�鏈夋爣绛撅紝鍙兘瀵艰嚧閲嶅彔锛屾牴鎹渶姹傝皟鏁� - } - }, - yAxis: { - type: 'value' - }, - series: [ - { - data: Array.from(new Set(series)).map((item) => - getCount(series, item) - ), - type: 'bar', - smooth: true - } - ] - }; - return option; - } -}; +// 閫氳繃 ECharts API 涓嬭浇鍥剧墖鐨勫嚱鏁� +function downloadChartImage(chart, fileName) { + if (!chart) return; // 纭繚鍥捐〃宸插垵濮嬪寲 + + // 鑾峰彇鍥捐〃鍥剧墖鏁版嵁锛堟敮鎸� png/jpeg 鏍煎紡锛宲ixelRatio 鎺у埗娓呮櫚搴︼級 + const dataURL = chart.getDataURL({ + type: 'png', // 鍥剧墖鏍煎紡 + pixelRatio: 2, // 鍍忕礌姣旓紝鍊艰秺澶у浘鐗囪秺娓呮櫚 + backgroundColor: '#fff', // 鑳屾櫙鑹诧紙榛樿閫忔槑锛� + excludeComponents: ['toolbox'] + }); + // 鍒涘缓涓嬭浇閾炬帴 + const link = document.createElement('a'); + link.href = dataURL; + // 璁剧疆涓嬭浇鏂囦欢鍚嶏紙鍙牴鎹疄闄呴渶姹傝皟鏁达級 + link.download = `${fileName}.png`; + // 娣诲姞鍒版枃妗e苟瑙﹀彂涓嬭浇 + document.body.appendChild(link); + link.click(); + // 娓呯悊閾炬帴鍏冪礌 + document.body.removeChild(link); +} + +export { pieChartOption, downloadChartImage }; diff --git a/src/utils/excel.js b/src/utils/excel.js index 07a0cc2..9caa91c 100644 --- a/src/utils/excel.js +++ b/src/utils/excel.js @@ -1,5 +1,7 @@ import * as XLSX from 'xlsx'; import FileSaver from 'file-saver'; +import { ElMessage } from 'element-plus'; + function conversionFromTable(elementId, title) { // 鑾峰彇琛ㄦ牸鍏冪礌 @@ -38,7 +40,7 @@ `${title}.xlsx` //淇敼鍚嶅瓧 ); //杩欓噷鍙互鏀惧叆浣犵殑鍥炶皟鍑芥暟 - alert('寮�濮嬩笅杞�'); + ElMessage.success('寮�濮嬩笅杞�'); } catch (e) { if (typeof console !== 'undefined') console.log(e, table_write); } diff --git a/src/views/fysp/data-product/ProdLawEnforceList.vue b/src/views/fysp/data-product/ProdLawEnforceList.vue index 940d70d..caed506 100644 --- a/src/views/fysp/data-product/ProdLawEnforceList.vue +++ b/src/views/fysp/data-product/ProdLawEnforceList.vue @@ -76,15 +76,11 @@ <el-icon class="is-loading" v-if="row._loading"> <Loading color="#409eff" /> </el-icon> - <div v-else> - <template v-if="row._problems.length > 0"> - <div v-for="(p, i) in row._problems" :key="p.guid"> - <el-text>{{ i + 1 }}銆�</el-text> - <el-text>{{ p.problemname }}</el-text> - </div> + <template v-else-if="row._problems.length > 0"> + <template v-for="(p, i) in row._problems" :key="p.guid"> + <br v-if="i > 0" />{{ i + 1 + '銆�' + p.problemname }} </template> - <el-text v-else>/</el-text> - </div> + </template> </template> </el-table-column> <!-- <el-table-column @@ -325,7 +321,7 @@ filterHandler(value, row, column) { const property = column['property']; return row[property] === value; - }, + } }, mounted() { this.addRefreshEvent(this.$refs.tableRef.doLayout); diff --git a/src/views/fysp/data-product/base-data-product/ManageBaseProd.vue b/src/views/fysp/data-product/base-data-product/ManageBaseProd.vue new file mode 100644 index 0000000..d956404 --- /dev/null +++ b/src/views/fysp/data-product/base-data-product/ManageBaseProd.vue @@ -0,0 +1,27 @@ +<template> + <CompProdManage :menu="menu" /> +</template> +<script setup> +import { ref } from 'vue'; +import CompProdManage from '@/views/fysp/data-product/components/CompProdManage.vue'; + +const menu = ref([ + { + name: '鍦烘櫙娓呭崟', + path: 'scene', + }, + { + name: '璇勪及娓呭崟', + path: 'evaluate' + }, + { + name: '鏁存敼娓呭崟', + path: 'inspection' + }, + { + name: '鐩戞祴鏁版嵁', + path: 'monitorData' + } +]); +</script> +<style scoped></style> diff --git a/src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue b/src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue index c9c31d5..b64f367 100644 --- a/src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue +++ b/src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue @@ -56,7 +56,7 @@ <script setup> import { ref, inject } from 'vue'; import dayjs from 'dayjs'; -import BaseProdProcess from '@/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; import dataprodbaseApi from '@/api/fysp/dataprodbaseApi.js'; import { conversionFromTable } from '@/utils/excel'; import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; diff --git a/src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue b/src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue index 10bd091..0e8db25 100644 --- a/src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue +++ b/src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue @@ -37,24 +37,35 @@ <el-table-column prop="cityname" label="甯�" width="90" /> <el-table-column prop="districtname" label="鍖哄幙" width="90" /> --> <el-table-column prop="subTask.townname" label="琛楅亾" width="80" /> + <el-table-column prop="problems.length" label="闂鏁�" width="60" /> + <el-table-column label="闂鎽樿" width="300"> + <template #default="{ row }"> + <template v-for="(value, index) in row.problems" :key="value.guid"> + <br v-if="index > 0" />{{ index + 1 + '銆�' + value.problemname }} + </template> + </template> + </el-table-column> <el-table-column - prop="problems.length" - label="闂鏁�" - width="60" - /> - <el-table-column prop="scoreLevel" label="闂鎽樿" width="70" /> - <el-table-column - prop="evaluate.resultscorebef" + prop="unChangeProblems.length" label="鏈暣鏀规暟" width="60" /> - <el-table-column prop="scoreLevel" label="鏈暣鏀归棶棰�" width="70" /> - <el-table-column + <el-table-column label="鏈暣鏀归棶棰�" width="300"> + <template #default="{ row }"> + <template + v-for="(value, index) in row.unChangeProblems" + :key="value.guid" + > + <br v-if="index > 0" />{{ index + 1 + '銆�' + value.problemname }} + </template> + </template> + </el-table-column> + <!-- <el-table-column prop="evaluate.updatedate" label="鏇存柊鏃堕棿" width="140" :formatter="timeFormat" - /> + /> --> </el-table> </template> </BaseProdProcess> @@ -62,7 +73,7 @@ <script setup> import { ref, inject } from 'vue'; import dayjs from 'dayjs'; -import BaseProdProcess from '@/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; import dataprodbaseApi from '@/api/fysp/dataprodbaseApi.js'; import { conversionFromTable } from '@/utils/excel'; import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; @@ -77,7 +88,12 @@ .fetchProdInspectionInfo(opt) .then((res) => { if (res.success) { - tableData.value = res.data; + tableData.value = res.data.map((item) => { + return { + ...item, + unChangeProblems: item.problems.filter((p) => !p.ischanged) + }; + }); } changeActive(); }) diff --git a/src/views/fysp/data-product/base-data-product/ProdMonitorDataInfo.vue b/src/views/fysp/data-product/base-data-product/ProdMonitorDataInfo.vue index 91bfefa..cc5e097 100644 --- a/src/views/fysp/data-product/base-data-product/ProdMonitorDataInfo.vue +++ b/src/views/fysp/data-product/base-data-product/ProdMonitorDataInfo.vue @@ -1,4 +1,98 @@ <template> - 1 + <BaseProdProcess + v-model:active="active" + @onStep1="onStep1" + @onStep2="onStep2" + @onStep3="onStep3" + :loading="loading" + > + <template #step2="{ contentHeight }"> + <el-table + id="prod-scene-table" + :data="tableData" + v-loading="loading" + :height="contentHeight + 'px'" + table-layout="fixed" + :show-overflow-tooltip="true" + size="small" + border + > + <el-table-column fixed="left" prop="index" label="鎺掑悕" width="50"> + </el-table-column> + <el-table-column + fixed="left" + prop="scene.name" + label="鍚嶇О" + :show-overflow-tooltip="true" + min-width="200" + > + </el-table-column> + <el-table-column prop="data.drAvg" label="骞冲潎鍊�(mg/m鲁)" width="100" /> + <el-table-column + prop="data.drOverAvgPer" + label="瓒呭尯鍧囧��" + width="80" + :formatter="ratioFormat" + /> + <el-table-column label="瓒呭競鍧囧��" width="80" /> + <!-- <el-table-column prop="provincename" label="鐪�" width="90" /> + <el-table-column prop="cityname" label="甯�" width="90" /> + <el-table-column prop="districtname" label="鍖哄幙" width="90" /> --> + <el-table-column prop="scene.townname" label="灞炲湴" width="110" /> + </el-table> + </template> + <!-- <template #step3></template> --> + </BaseProdProcess> </template> -<script setup></script> \ No newline at end of file +<script setup> +import { ref, inject } from 'vue'; +import dayjs from 'dayjs'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; +import dataprodbaseApi from '@/api/fysp/dataprodbaseApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; + +const { active, changeActive } = useProdStepChange(); +const loading = ref(false); +const tableData = ref([]); + +function onStep1(opt) { + loading.value = true; + dataprodbaseApi + .fetchProdMonitorDataInfo(opt) + .then((res) => { + if (res.success) { + tableData.value = res.data + .sort((a, b) => { + return b.data.drAvg - a.data.drAvg; + }) + .map((item, index) => { + return { + ...item, + index: index + 1 + }; + }); + } + changeActive(); + }) + .finally(() => { + loading.value = false; + }); +} + +function onStep2() { + changeActive(); +} + +function onStep3(val) { + if (val.downloadType == '1') { + loading.value = true; + conversionFromTable('prod-scene-table', '鍦ㄧ嚎鐩戞祴鏁版嵁娓呭崟'); + loading.value = false; + } +} + +function ratioFormat(row, column, cellValue, index) { + return Math.round(cellValue * 1000) / 10 + '%'; +} +</script> diff --git a/src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue b/src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue index ef1323e..1bc9117 100644 --- a/src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue +++ b/src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue @@ -6,9 +6,6 @@ @onStep3="onStep3" :loading="loading" > - <!-- <template #step1> - <ProdQueryOpt :loading="loading" @submit="onSearch"> </ProdQueryOpt> - </template> --> <template #step2="{ contentHeight }"> <el-table id="prod-scene-table" @@ -50,14 +47,12 @@ /> --> </el-table> </template> - <!-- <template #step3></template> --> </BaseProdProcess> </template> <script setup> import { ref, inject } from 'vue'; import dayjs from 'dayjs'; -import BaseProdProcess from '@/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue'; -import ProdQueryOpt from '@/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; import dataprodbaseApi from '@/api/fysp/dataprodbaseApi.js'; import { conversionFromTable } from '@/utils/excel'; import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; diff --git a/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue b/src/views/fysp/data-product/components/BaseProdProcess.vue similarity index 97% rename from src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue rename to src/views/fysp/data-product/components/BaseProdProcess.vue index 8d533e7..699d958 100644 --- a/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue +++ b/src/views/fysp/data-product/components/BaseProdProcess.vue @@ -111,8 +111,8 @@ <script setup> import { computed, inject, ref, watch, onMounted, onUnmounted } from 'vue'; import { unCalc } from '@/utils/css-util'; -import ProdQueryOpt from '@/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue'; -import ProdDownload from '@/views/fysp/data-product/base-data-product/components/ProdDownload.vue'; +import ProdQueryOpt from '@/views/fysp/data-product/components/ProdQueryOpt.vue'; +import ProdDownload from '@/views/fysp/data-product/components/ProdDownload.vue'; const props = defineProps({ active: { diff --git a/src/views/fysp/data-product/base-data-product/ProdManage.vue b/src/views/fysp/data-product/components/CompProdManage.vue similarity index 72% rename from src/views/fysp/data-product/base-data-product/ProdManage.vue rename to src/views/fysp/data-product/components/CompProdManage.vue index e04d292..e7d3397 100644 --- a/src/views/fysp/data-product/base-data-product/ProdManage.vue +++ b/src/views/fysp/data-product/components/CompProdManage.vue @@ -2,7 +2,7 @@ <el-affix> <el-menu ref="menuRef" - default-active="scene" + :default-active="menu.length > 0 ? menu[0].path : ''" ellipsis mode="horizontal" > @@ -28,35 +28,41 @@ </template> <script setup> import { ref, onMounted, provide, inject, computed } from 'vue'; -import { useRouter, useRoute } from 'vue-router'; +import { useRouter } from 'vue-router'; const contentMaxHeight = inject('contentMaxHeight'); +const props = defineProps({ + menu: { + type: Array, + default: () => [] + } +}) + const router = useRouter(); -const route = useRoute(); const menuRef = ref(null); const height = ref(contentMaxHeight.value); -const menu = ref([ - { - name: '鍦烘櫙娓呭崟', - path: 'scene', - selected: true - }, - { - name: '璇勪及娓呭崟', - path: 'evaluate' - }, - { - name: '鏁存敼娓呭崟', - path: 'inspection' - }, - { - name: '鐩戞祴鏁版嵁', - path: 'monitorData' - } -]); +// const menu = ref([ +// { +// name: '鍦烘櫙娓呭崟', +// path: 'scene', +// selected: true +// }, +// { +// name: '璇勪及娓呭崟', +// path: 'evaluate' +// }, +// { +// name: '鏁存敼娓呭崟', +// path: 'inspection' +// }, +// { +// name: '鐩戞祴鏁版嵁', +// path: 'monitorData' +// } +// ]); const navPage = (item) => { if (item.index) { diff --git a/src/views/fysp/data-product/components/CompProdTextGenerator.vue b/src/views/fysp/data-product/components/CompProdTextGenerator.vue new file mode 100644 index 0000000..43d4f90 --- /dev/null +++ b/src/views/fysp/data-product/components/CompProdTextGenerator.vue @@ -0,0 +1,25 @@ +<template> + <el-input v-model="textarea" autosize type="textarea" placeholder="" /> +</template> +<script setup> +import { computed, ref } from 'vue'; + +const props = defineProps({ + // 妯℃澘 + template: { + type: String, + default: '' + }, + // 鍙傛暟 + params: { + type: Object, + default: () => {} + } +}); + +const textarea = computed(() => { + return props.template.replace(/{(\w+)}/g, (match, p1) => { + return props.params[p1] || ''; + }); +}); +</script> diff --git a/src/views/fysp/data-product/base-data-product/components/ProdDownload.vue b/src/views/fysp/data-product/components/ProdDownload.vue similarity index 100% rename from src/views/fysp/data-product/base-data-product/components/ProdDownload.vue rename to src/views/fysp/data-product/components/ProdDownload.vue diff --git a/src/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue b/src/views/fysp/data-product/components/ProdQueryOpt.vue similarity index 100% rename from src/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue rename to src/views/fysp/data-product/components/ProdQueryOpt.vue diff --git a/src/views/fysp/data-product/components/ProdQueryOptCompare.vue b/src/views/fysp/data-product/components/ProdQueryOptCompare.vue new file mode 100644 index 0000000..0935f07 --- /dev/null +++ b/src/views/fysp/data-product/components/ProdQueryOptCompare.vue @@ -0,0 +1,102 @@ +<template> + <el-card shadow="never"> + <template #header> + <div><el-text tag="b" size="large">浜у搧鐢熸垚閫夐」</el-text></div> + </template> + <el-form :inline="true" :model="formSearch"> + <FYOptionTopTask v-model:value="formSearch.topTask"></FYOptionTopTask> + <FYOptionScene + :allOption="false" + :type="2" + v-model:value="formSearch.scenetype" + ></FYOptionScene> + </el-form> + <el-form :inline="true" :model="formSearch2"> + <FYOptionTopTask v-model:value="formSearch2.topTask"></FYOptionTopTask> + </el-form> + <template #footer> + <el-row v-show="active" justify="end"> + <el-button + type="primary" + size="default" + :loading="loading" + @click="submit" + >鐢熸垚</el-button + > + </el-row> + </template> + </el-card> +</template> +<script setup> +import { ref, computed } from 'vue'; +import dayjs from 'dayjs'; + +const props = defineProps({ + loading: { + type: Boolean, + default: false + }, + active: { + type: Boolean, + default: true + } +}); +const emit = defineEmits(['submit']); + +const formSearch = ref({ + topTask: {}, + scenetype: {} +}); + +const formSearch2 = ref({ + topTask: {} +}); + +const submit = () => { + const opt1 = { + topTaskId: formSearch.value.topTask.tguid, + topTaskName: formSearch.value.topTask.name, + provinceCode: formSearch.value.topTask.provincecode, + provinceName: formSearch.value.topTask.provincename, + cityCode: formSearch.value.topTask.citycode, + cityName: formSearch.value.topTask.cityname, + districtCode: formSearch.value.topTask.districtcode, + districtName: formSearch.value.topTask.districtname, + townCode: formSearch.value.topTask.towncode, + townName: formSearch.value.topTask.townname, + startTime: dayjs(formSearch.value.topTask.starttime).format( + 'YYYY-MM-DD HH:mm:ss' + ), + endTime: dayjs(formSearch.value.topTask.endtime) + .add(1, 'day') + .add(-1, 'second') + .format('YYYY-MM-DD HH:mm:ss'), + sceneTypeId: formSearch.value.scenetype.value, + sceneTypeName: formSearch.value.scenetype.label, + needCache: true + }; + const opt2 = { + topTaskId: formSearch2.value.topTask.tguid, + topTaskName: formSearch2.value.topTask.name, + provinceCode: formSearch2.value.topTask.provincecode, + provinceName: formSearch2.value.topTask.provincename, + cityCode: formSearch2.value.topTask.citycode, + cityName: formSearch2.value.topTask.cityname, + districtCode: formSearch2.value.topTask.districtcode, + districtName: formSearch2.value.topTask.districtname, + townCode: formSearch2.value.topTask.towncode, + townName: formSearch2.value.topTask.townname, + startTime: dayjs(formSearch2.value.topTask.starttime).format( + 'YYYY-MM-DD HH:mm:ss' + ), + endTime: dayjs(formSearch2.value.topTask.endtime) + .add(1, 'day') + .add(-1, 'second') + .format('YYYY-MM-DD HH:mm:ss'), + sceneTypeId: formSearch.value.scenetype.value, + sceneTypeName: formSearch.value.scenetype.label, + needCache: true + }; + emit('submit', [opt1, opt2]); +}; +</script> diff --git a/src/views/fysp/data-product/middle-data-product/ManageMiddleProd.vue b/src/views/fysp/data-product/middle-data-product/ManageMiddleProd.vue new file mode 100644 index 0000000..cb2ee56 --- /dev/null +++ b/src/views/fysp/data-product/middle-data-product/ManageMiddleProd.vue @@ -0,0 +1,31 @@ +<template> + <CompProdManage :menu="menu" /> +</template> +<script setup> +import { ref } from 'vue'; +import CompProdManage from '@/views/fysp/data-product/components/CompProdManage.vue'; + +const menu = ref([ + { + name: '鏈堝害宸℃煡鎯呭喌姹囨��', + path: 'inspectionSummary', + }, + { + name: '鏈堝害闂姹囨��', + path: 'problemTypeSummary' + }, + { + name: '鍒嗚闀囧崟鍦烘櫙闂鏁板潎鍊�', + path: 'problemCountSummary' + }, + { + name: '鐩戞祴璁惧姹囨��', + path: 'monitorDeviceSummary' + }, + { + name: '璇勪及鎯呭喌姹囨��', + path: 'evaluationSummary' + } +]); +</script> +<style scoped></style> diff --git a/src/views/fysp/data-product/middle-data-product/ProdEvaluationSummary.vue b/src/views/fysp/data-product/middle-data-product/ProdEvaluationSummary.vue new file mode 100644 index 0000000..21ce1c9 --- /dev/null +++ b/src/views/fysp/data-product/middle-data-product/ProdEvaluationSummary.vue @@ -0,0 +1,28 @@ +<template> + <BaseProdProcess + v-model:active="active" + @onStep1="onStep1" + @onStep2="onStep2" + @onStep3="onStep3" + :loading="loading" + > + </BaseProdProcess> +</template> +<script setup> +import { ref } from 'vue'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; +import dataprodmiddleApi from '@/api/fysp/dataprodmiddleApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; + +const { active, changeActive } = useProdStepChange(); +const loading = ref(false); + +function onStep1(opt) {} + +function onStep2() { + changeActive(); +} + +function onStep3(val) {} +</script> diff --git a/src/views/fysp/data-product/middle-data-product/ProdInspectionSummary.vue b/src/views/fysp/data-product/middle-data-product/ProdInspectionSummary.vue new file mode 100644 index 0000000..3738cda --- /dev/null +++ b/src/views/fysp/data-product/middle-data-product/ProdInspectionSummary.vue @@ -0,0 +1,75 @@ +<template> + <BaseProdProcess + v-model:active="active" + @onStep1="onStep1" + @onStep2="onStep2" + @onStep3="onStep3" + :loading="loading" + > + <template #step2="{ contentHeight }"> + <el-scrollbar :height="contentHeight"> + <el-card shadow="never"> + <el-form :inline="false" label-position="left" label-width="150px"> + <el-form-item label="宸℃煡鍦烘櫙鎬绘暟"> + <el-text>{{ data.sceneCount }}</el-text> + </el-form-item> + <el-form-item label="宸℃煡鐐规"> + <el-text>{{ data.pointCount }}</el-text> + </el-form-item> + <el-form-item label="澶嶆牳鐐规"> + <el-text>{{ data.reviewPointCount }}</el-text> + </el-form-item> + <el-form-item label="鍋滃伐鍦烘櫙鏁�"> + <el-text>{{ data.stopSceneCount }}</el-text> + </el-form-item> + <el-form-item label="瀹屽伐鍦烘櫙鏁�"> + <el-text>{{ data.completeSceneCount }}</el-text> + </el-form-item> + </el-form> + <!-- <CompProdTextGenerator + :template="template" + :params="params" + /> --> + </el-card> + </el-scrollbar> + </template> + </BaseProdProcess> +</template> +<script setup> +import { ref } from 'vue'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; +import CompProdTextGenerator from '@/views/fysp/data-product/components/CompProdTextGenerator.vue'; +import dataprodmiddleApi from '@/api/fysp/dataprodmiddleApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; +import { ElMessage } from 'element-plus'; + +const { active, changeActive } = useProdStepChange(); +const loading = ref(false); +const data = ref({}); + +const template = ref('2025骞�7鏈堬紝绗笁鏂瑰湪鍖虹敓鎬佺幆澧冨眬鎸囧涓嬪杈栧尯鍐�72瀹跺伐鍦板紑灞曚簡鎵皹姹℃煋闃叉不鐜板満宸℃煡銆傚闂杈冧弗閲嶆垨鎵皹绠℃帶涓嶅埌浣嶅伐鍦拌繘琛�4瀹舵澶嶆牳锛屾湰杞叡璁″贰鏌�76瀹舵锛�7鏈堥厤鍚堣仈鍚堟墽娉曟垨鏂板伐鍦颁氦搴曞璐叡鍑哄姩6缁�7浜烘銆�'); +const params = ref({}); + +function onStep1(opt) { + loading.value = true; + dataprodmiddleApi + .fetchInspectionSummary(opt) + .then((res) => { + if (res.success) { + data.value = res.data; + } + changeActive(); + }) + .finally(() => { + loading.value = false; + }); +} + +function onStep2() { + // changeActive(); + ElMessage.error('鏆備笉鎻愪緵涓嬭浇'); +} + +function onStep3(val) {} +</script> diff --git a/src/views/fysp/data-product/middle-data-product/ProdMonitorDeviceSummary.vue b/src/views/fysp/data-product/middle-data-product/ProdMonitorDeviceSummary.vue new file mode 100644 index 0000000..21ce1c9 --- /dev/null +++ b/src/views/fysp/data-product/middle-data-product/ProdMonitorDeviceSummary.vue @@ -0,0 +1,28 @@ +<template> + <BaseProdProcess + v-model:active="active" + @onStep1="onStep1" + @onStep2="onStep2" + @onStep3="onStep3" + :loading="loading" + > + </BaseProdProcess> +</template> +<script setup> +import { ref } from 'vue'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; +import dataprodmiddleApi from '@/api/fysp/dataprodmiddleApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; + +const { active, changeActive } = useProdStepChange(); +const loading = ref(false); + +function onStep1(opt) {} + +function onStep2() { + changeActive(); +} + +function onStep3(val) {} +</script> diff --git a/src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue b/src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue new file mode 100644 index 0000000..fe5212f --- /dev/null +++ b/src/views/fysp/data-product/middle-data-product/ProdProblemCountSummary.vue @@ -0,0 +1,33 @@ +<template> + <BaseProdProcess + v-model:active="active" + @onStep2="onStep2" + @onStep3="onStep3" + :loading="loading" + > + <template #step1> + <ProdQueryOptCompare @submit="onStep1"></ProdQueryOptCompare> + </template> + </BaseProdProcess> +</template> +<script setup> +import { ref } from 'vue'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; +import dataprodmiddleApi from '@/api/fysp/dataprodmiddleApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; +import ProdQueryOptCompare from '@/views/fysp/data-product/components/ProdQueryOptCompare.vue'; + +const { active, changeActive } = useProdStepChange(); +const loading = ref(false); + +function onStep1(opts) { + console.log('onStep1', opts); +} + +function onStep2() { + changeActive(); +} + +function onStep3(val) {} +</script> diff --git a/src/views/fysp/data-product/middle-data-product/ProdProblemTypeSummary.vue b/src/views/fysp/data-product/middle-data-product/ProdProblemTypeSummary.vue new file mode 100644 index 0000000..181450a --- /dev/null +++ b/src/views/fysp/data-product/middle-data-product/ProdProblemTypeSummary.vue @@ -0,0 +1,127 @@ +<template> + <BaseProdProcess + v-model:active="active" + @onStep1="onStep1" + @onStep2="onStep2" + @onStep3="onStep3" + :loading="loading" + > + <template #step2="{ contentHeight }"> + <el-scrollbar :height="contentHeight"> + <el-row> + <el-col :span="24"> + <el-table + id="prod-problem-type-table" + :data="tableData" + v-loading="loading" + table-layout="fixed" + :show-overflow-tooltip="true" + size="small" + border + > + <el-table-column + fixed="left" + type="index" + label="缂栧彿" + width="50" + > + </el-table-column> + <el-table-column + fixed="left" + prop="typeName" + label="闂绫诲瀷" + min-width="200" + > + </el-table-column> + <el-table-column prop="count" label="鏁伴噺" min-width="50" /> + <el-table-column + prop="ratio" + label="鏈湀鍗犳瘮" + min-width="70" + :formatter="ratioFormat" + /> + <el-table-column + prop="ratioDiff" + label="杈冧笂鏈堝崰姣斿彉鍖�" + min-width="70" + :formatter="ratioFormat" + /> + </el-table> + </el-col> + <el-col :span="24"> + <el-row justify="center"> + <div ref="chartRef" style="height: 400px; width: 100%;max-width: 800px;"></div> + </el-row> + </el-col> + </el-row> + </el-scrollbar> + </template> + </BaseProdProcess> +</template> +<script setup> +import { ref } from 'vue'; +import * as echarts from 'echarts'; +import BaseProdProcess from '@/views/fysp/data-product/components/BaseProdProcess.vue'; +import dataprodmiddleApi from '@/api/fysp/dataprodmiddleApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; +import dayjs from 'dayjs'; +import { pieChartOption, downloadChartImage } from '@/utils/echart-util.js'; + +const { active, changeActive } = useProdStepChange(); +const loading = ref(false); +const tableData = ref([]); +const chartRef = ref(null); +let chart; + +function onStep1(opt) { + loading.value = true; + dataprodmiddleApi + .fetchProblemTypeSummary(opt) + .then((res) => { + if (res.success) { + tableData.value = res.data; + } + changeActive(); + setTimeout(() => { + genChart(opt); + }, 500); + }) + .finally(() => { + loading.value = false; + }); +} + +function onStep2() { + changeActive(); +} + +function onStep3(val) { + if (val.downloadType == '1') { + loading.value = true; + // conversionFromTable('prod-problem-type-table', '鎵皹姹℃煋闂绫诲瀷鍗犳瘮娓呭崟'); + downloadChartImage(chart, '鎵皹姹℃煋闂绫诲瀷鍗犳瘮'); + loading.value = false; + } +} + +function genChart(opt) { + if (chart == undefined) { + chart = echarts.init(chartRef.value); + } + const startTime = dayjs(opt.startTime).format('YYYY骞碝M鏈�'); + const option = pieChartOption(); + option.title.text = `${startTime}鎵皹姹℃煋闂绫诲瀷鍗犳瘮`; + option.legend.data = tableData.value.map((item) => item.typeName); + option.series[0].name = '闂绫诲瀷'; + option.series[0].data = tableData.value.map((item) => ({ + name: item.typeName, + value: item.count + })); + chart.setOption(option); +} + +function ratioFormat(row, column, cellValue, index) { + return Math.round(cellValue * 1000) / 10 + '%'; +} +</script> diff --git a/src/views/fysp/support/JingAnNightConstruction.vue b/src/views/fysp/support/JingAnNightConstruction.vue index c4066bf..c610f63 100644 --- a/src/views/fysp/support/JingAnNightConstruction.vue +++ b/src/views/fysp/support/JingAnNightConstruction.vue @@ -4,9 +4,19 @@ :total-count="total" @search="onSearch" :extraHeight="tabsHeaderHeight" + :defaultPageSize="10" > - <!-- <template #options> </template> - <template #buttons> </template> --> + <template #options> + <FYOptionLocation + :disabled="true" + :checkStrictly="false" + :initValue="false" + :allOption="false" + :level="3" + v-model:value="formSearch._locations" + ></FYOptionLocation> + </template> + <!-- <template #buttons> </template> --> <template #table-column> <el-table-column fixed="left" @@ -97,6 +107,16 @@ const tabsHeaderHeight = inject('tabsHeaderHeight', 0); +const formSearch = ref({ + _locations: { + pCode: '31', + pName: '涓婃捣甯�', + cCode: '3100', + cName: '涓婃捣甯�', + dCode: '310106', + dName: '闈欏畨鍖�' + } +}); // 澶滈棿鏂藉伐璁板綍鍙婃�绘暟 const data = ref([]); const total = ref(0); -- Gitblit v1.9.3