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