liuxing il y a 1 an
Parent
commit
788a9a9c33

+ 17 - 10
app/src/api/detail.js

@@ -4,7 +4,7 @@ import { request } from "@zhgkpt/utils";
 export function getBuildDetail(id) {
   return request({
     url: "/system/gcjzjcxxcj/detail?id=" + id,
-    methods: "get"
+    methods: "get",
   });
 }
 
@@ -13,7 +13,7 @@ export function getXfss(params) {
   return request({
     url: "/system/xfss/list",
     methods: "get",
-    params
+    params,
   });
 }
 
@@ -22,7 +22,7 @@ export function getRzdw(params) {
   return request({
     url: "/system/rzdw/list",
     methods: "get",
-    params
+    params,
   });
 }
 
@@ -31,7 +31,7 @@ export function getLshz(params) {
   return request({
     url: "/system/lshz/list",
     methods: "get",
-    params
+    params,
   });
 }
 
@@ -40,17 +40,16 @@ export function getYh(params) {
   return request({
     url: "/system/yh/list",
     methods: "get",
-    params
+    params,
   });
 }
 
-
 // 获取接入数
 export function getXfjrs(params) {
   return request({
     url: "/system/zxgjtj/list",
     methods: "get",
-    params
+    params,
   });
 }
 
@@ -59,7 +58,7 @@ export function getFxdj(params) {
   return request({
     url: "/system/zl/jcxxList/zyfxd",
     methods: "get",
-    params
+    params,
   });
 }
 
@@ -69,6 +68,14 @@ export function getQrcode(params) {
   return request({
     url: "/system/api/qrcode",
     methods: "get",
-    params
+    params,
+  });
+}
+
+export function getFile(params) {
+  return request({
+    url: "/system/gcjzjcxxcj/picUrl",
+    methods: "get",
+    params,
   });
-}
+}

BIN
app/src/assets/images/pdf.png


+ 530 - 463
app/src/components/Monitor3D.vue

@@ -1,476 +1,543 @@
 <script setup>
-	import {
-		onMounted,
-		ref,
-		watch
-	} from "vue";
-	import * as echarts from "echarts";
-	import "echarts-gl";
-	const props = defineProps({
-		data: Object,
-	});
-	let chart, option;
-	const pieChart3d = ref();
-
-	function initChart() {
-		chart = echarts.init(pieChart3d.value);
-		// 传入数据生成 option
-		option = getPie3D(
-			[{
-					name: "生命通道监控点位",
-					value: props.data.smtd.zs || 0,
-					label: {
-						show: true
-					}
-				},
-				{
-					name: "电气火灾监测点位",
-					value: props.data.dqhz.zs || 0,
-					label: {
-						show: true
-					}
-				},
-				{
-					name: "水压检测点位",
-					value: props.data.sy.zs || 0,
-					label: {
-						show: true
-					}
-				},
-				{
-					name: "火灾报警主机监测点位",
-					value: props.data.hzbjzj.zs || 0,
-					label: {
-						show: true
-					}
-				},
-				{
-					name: "消防监控室人员离岗检测点位",
-					value: props.data.xfkzs.zs || 0,
-					label: {
-						show: true
-					}
-				},
-			],
-			0
-		);
-
-		// 监听鼠标事件,实现饼图选中效果(单选),近似实现高亮(放大)效果。
-		let hoveredIndex = "";
-		// 准备重新渲染扇形所需的参数
-		let isSelected;
-		let isHovered;
-		let startRatio;
-		let endRatio;
-		let k;
-
-		// 监听 mouseover,近似实现高亮(放大)效果
-		chart.on("mouseover", function(params) {
-			// 如果触发 mouseover 的扇形当前已高亮,则不做操作
-			if (hoveredIndex === params.seriesIndex) {
-				return;
-
-				// 否则进行高亮及必要的取消高亮操作
-			} else {
-				// 如果当前有高亮的扇形,取消其高亮状态(对 option 更新)
-				if (hoveredIndex !== "") {
-					// 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 false。
-					isSelected = option.series[hoveredIndex].pieStatus.selected;
-					isHovered = false;
-					startRatio = option.series[hoveredIndex].pieData.startRatio;
-					endRatio = option.series[hoveredIndex].pieData.endRatio;
-					k = option.series[hoveredIndex].pieStatus.k;
-
-					// 对当前点击的扇形,执行取消高亮操作(对 option 更新)
-					option.series[hoveredIndex].parametricEquation = getParametricEquation(
-						startRatio,
-						endRatio,
-						isSelected,
-						isHovered,
-						k,
-						option.series[hoveredIndex].pieData.value
-					);
-					option.series[hoveredIndex].pieStatus.hovered = isHovered;
-
-					// 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
-					hoveredIndex = "";
-				}
-
-				// 如果触发 mouseover 的扇形不是透明圆环,将其高亮(对 option 更新)
-				if (params.seriesName !== "mouseoutSeries") {
-					// 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
-					isSelected = option.series[params.seriesIndex].pieStatus.selected;
-					isHovered = true;
-					startRatio = option.series[params.seriesIndex].pieData.startRatio;
-					endRatio = option.series[params.seriesIndex].pieData.endRatio;
-					k = option.series[params.seriesIndex].pieStatus.k;
-
-					// 对当前点击的扇形,执行高亮操作(对 option 更新)
-					option.series[params.seriesIndex].parametricEquation =
-						getParametricEquation(
-							startRatio,
-							endRatio,
-							isSelected,
-							isHovered,
-							k,
-							option.series[params.seriesIndex].pieData.value + 5
-						);
-					option.series[params.seriesIndex].pieStatus.hovered = isHovered;
-
-					// 记录上次高亮的扇形对应的系列号 seriesIndex
-					hoveredIndex = params.seriesIndex;
-				}
-
-				// 使用更新后的 option,渲染图表
-				chart.setOption(option);
-			}
-		});
-
-		// 修正取消高亮失败的 bug
-		chart.on("globalout", function() {
-			if (hoveredIndex !== "") {
-				// 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
-				isSelected = option.series[hoveredIndex].pieStatus.selected;
-				isHovered = false;
-				k = option.series[hoveredIndex].pieStatus.k;
-				startRatio = option.series[hoveredIndex].pieData.startRatio;
-				endRatio = option.series[hoveredIndex].pieData.endRatio;
-
-				// 对当前点击的扇形,执行取消高亮操作(对 option 更新)
-				option.series[hoveredIndex].parametricEquation = getParametricEquation(
-					startRatio,
-					endRatio,
-					isSelected,
-					isHovered,
-					k,
-					option.series[hoveredIndex].pieData.value
-				);
-				option.series[hoveredIndex].pieStatus.hovered = isHovered;
-
-				// 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
-				hoveredIndex = "";
-			}
-
-			// 使用更新后的 option,渲染图表
-			chart.setOption(option);
-		});
-
-		if (option && typeof option === "object") {
-			chart.setOption(option);
-		}
-	}
-
-	watch(() => props.data, () => {
-		initChart()
-	}, {
-		deep: true
+import { onMounted, ref, watch } from "vue";
+import * as echarts from "echarts";
+import "echarts-gl";
+const props = defineProps({
+  data: Object,
+});
+let chart, option;
+const pieChart3d = ref();
+
+function initChart() {
+  chart = echarts.init(pieChart3d.value);
+  // 传入数据生成 option
+  const data = [];
+  if (props.data.smtd.zs) {
+    data.push({
+      name: "生命通道监控点位",
+      value: props.data.smtd.zs || 0,
+      label: {
+        show: true,
+      },
+    });
+  }
+  if (props.data.dqhz.zs) {
+    data.push({
+      name: "电气火灾监测点位",
+      value: props.data.dqhz.zs || 0,
+      label: {
+        show: true,
+      },
+    });
+  }
+  if (props.data.sy.zs) {
+    data.push({
+      name: "水压检测点位",
+      value: props.data.sy.zs || 0,
+      label: {
+        show: true,
+      },
+    });
+  }
+  if (props.data.hzbjzj.zs) {
+    data.push({
+      name: "火灾报警主机监测点位",
+      value: props.data.hzbjzj.zs || 0,
+      label: {
+        show: true,
+      },
+    });
+  }
+  if (props.data.xfkzs.zs) {
+    data.push({
+      name: "消防监控室人员离岗检测点位",
+      value: props.data.xfkzs.zs || 0,
+      label: {
+        show: true,
+      },
+    });
+  }
+  option = getPie3D(data, 0);
+
+  // 监听鼠标事件,实现饼图选中效果(单选),近似实现高亮(放大)效果。
+  let hoveredIndex = "";
+  // 准备重新渲染扇形所需的参数
+  let isSelected;
+  let isHovered;
+  let startRatio;
+  let endRatio;
+  let k;
+
+  // 监听 mouseover,近似实现高亮(放大)效果
+  chart.on("mouseover", function (params) {
+    // 如果触发 mouseover 的扇形当前已高亮,则不做操作
+    if (hoveredIndex === params.seriesIndex) {
+      return;
+
+      // 否则进行高亮及必要的取消高亮操作
+    } else {
+      // 如果当前有高亮的扇形,取消其高亮状态(对 option 更新)
+      if (hoveredIndex !== "") {
+        // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 false。
+        isSelected = option.series[hoveredIndex].pieStatus.selected;
+        isHovered = false;
+        startRatio = option.series[hoveredIndex].pieData.startRatio;
+        endRatio = option.series[hoveredIndex].pieData.endRatio;
+        k = option.series[hoveredIndex].pieStatus.k;
+
+        // 对当前点击的扇形,执行取消高亮操作(对 option 更新)
+        option.series[hoveredIndex].parametricEquation = getParametricEquation(
+          startRatio,
+          endRatio,
+          isSelected,
+          isHovered,
+          k,
+          option.series[hoveredIndex].pieData.value
+        );
+        option.series[hoveredIndex].pieStatus.hovered = isHovered;
+
+        // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
+        hoveredIndex = "";
+      }
+
+      // 如果触发 mouseover 的扇形不是透明圆环,将其高亮(对 option 更新)
+      if (params.seriesName !== "mouseoutSeries") {
+        // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
+        isSelected = option.series[params.seriesIndex].pieStatus.selected;
+        isHovered = true;
+        startRatio = option.series[params.seriesIndex].pieData.startRatio;
+        endRatio = option.series[params.seriesIndex].pieData.endRatio;
+        k = option.series[params.seriesIndex].pieStatus.k;
+
+        // 对当前点击的扇形,执行高亮操作(对 option 更新)
+        option.series[params.seriesIndex].parametricEquation =
+          getParametricEquation(
+            startRatio,
+            endRatio,
+            isSelected,
+            isHovered,
+            k,
+            option.series[params.seriesIndex].pieData.value + 5
+          );
+        option.series[params.seriesIndex].pieStatus.hovered = isHovered;
+
+        // 记录上次高亮的扇形对应的系列号 seriesIndex
+        hoveredIndex = params.seriesIndex;
+      }
+
+      // 使用更新后的 option,渲染图表
+      chart.setOption(option);
+    }
+  });
+
+  // 修正取消高亮失败的 bug
+  chart.on("globalout", function () {
+    if (hoveredIndex !== "") {
+      // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
+      isSelected = option.series[hoveredIndex].pieStatus.selected;
+      isHovered = false;
+      k = option.series[hoveredIndex].pieStatus.k;
+      startRatio = option.series[hoveredIndex].pieData.startRatio;
+      endRatio = option.series[hoveredIndex].pieData.endRatio;
+
+      // 对当前点击的扇形,执行取消高亮操作(对 option 更新)
+      option.series[hoveredIndex].parametricEquation = getParametricEquation(
+        startRatio,
+        endRatio,
+        isSelected,
+        isHovered,
+        k,
+        option.series[hoveredIndex].pieData.value
+      );
+      option.series[hoveredIndex].pieStatus.hovered = isHovered;
+
+      // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
+      hoveredIndex = "";
+    }
+
+    // 使用更新后的 option,渲染图表
+    chart.setOption(option);
+  });
+
+  if (option && typeof option === "object") {
+    chart.setOption(option);
+  }
+}
+
+watch(
+  () => props.data,
+  () => {
+    initChart();
+  },
+  {
+    deep: true,
+  }
+);
+
+onMounted(() => {
+  initChart();
+});
+
+defineExpose({
+  legendToggleSelect(name) {
+    chart.dispatchAction({
+      type: "legendToggleSelect",
+      // 图例名称
+      name: name,
+    });
+  },
+});
+
+// 生成扇形的曲面参数方程
+function getParametricEquation(
+  startRatio,
+  endRatio,
+  isSelected,
+  isHovered,
+  k,
+  h
+) {
+  // 计算
+  const midRatio = (startRatio + endRatio) / 2;
+  const startRadian = startRatio * Math.PI * 2;
+  const endRadian = endRatio * Math.PI * 2;
+  const midRadian = midRatio * Math.PI * 2;
+
+  // 如果只有一个扇形,则不实现选中效果。
+  if (startRatio === 0 && endRatio === 1) {
+    // eslint-disable-next-line no-param-reassign
+    isSelected = false;
+  }
+
+  // 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
+  // eslint-disable-next-line no-param-reassign
+  k = typeof k !== "undefined" ? k : 1 / 3;
+
+  // 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
+  const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
+  const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
+
+  // 计算高亮效果的放大比例(未高亮,则比例为 1)
+  const hoverRate = isHovered ? 1.05 : 1;
+
+  // 返回曲面参数方程
+  return {
+    u: {
+      min: -Math.PI,
+      max: Math.PI * 3,
+      step: Math.PI / 32,
+    },
+
+    v: {
+      min: 0,
+      max: Math.PI * 2,
+      step: Math.PI / 20,
+    },
+
+    x(u, v) {
+      if (u < startRadian) {
+        return (
+          offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
+        );
+      }
+      if (u > endRadian) {
+        return (
+          offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
+        );
+      }
+      return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
+    },
+
+    y(u, v) {
+      if (u < startRadian) {
+        return (
+          offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
+        );
+      }
+      if (u > endRadian) {
+        return (
+          offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
+        );
+      }
+      return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
+    },
+
+    z(u, v) {
+      if (u < -Math.PI * 0.5) {
+        return Math.sin(u);
+      }
+      if (u > Math.PI * 2.5) {
+        return Math.sin(u);
+      }
+      return Math.sin(v) > 0 ? 1 : -1;
+    },
+  };
+}
+// 生成模拟 3D 饼图的配置项
+function getPie3D(pieData, internalDiameterRatio) {
+  const series = [];
+  // 总和
+  let sumValue = 0;
+  let startValue = 0;
+  let endValue = 0;
+  const legendData = [];
+  const k =
+    typeof internalDiameterRatio !== "undefined"
+      ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
+      : 1 / 3;
+
+  let labelSeries = {
+    id: "labelSeries",
+    type: "bar3D",
+    //zlevel:-9,
+    barSize: [0, 0],
+    data: [],
+    label: {
+      show: true,
+      formatter: function (params) {
+        return `${params.value[3]}`;
+      },
+      color: "#fff",
+      fontSize: "18px",
+    },
+  };
+  // 为每一个饼图数据,生成一个 series-surface 配置
+  for (let i = 0; i < pieData.length; i += 1) {
+    sumValue += pieData[i].value;
+    // console.log(pieData[i].name);
+    const seriesItem = {
+      name:
+        typeof pieData[i].name === "undefined" ? `series${i}` : pieData[i].name,
+      type: "surface",
+      parametric: true,
+      wireframe: {
+        show: false,
+      },
+      pieData: pieData[i],
+      pieStatus: {
+        selected: false,
+        hovered: false,
+        k,
+      },
+      // radius: 'dataValue',
+    };
+    if (typeof pieData[i].itemStyle !== "undefined") {
+      const { itemStyle } = pieData[i];
+      typeof pieData[i].itemStyle.color !== "undefined"
+        ? (itemStyle.color = pieData[i].itemStyle.color)
+        : null;
+      typeof pieData[i].itemStyle.opacity !== "undefined"
+        ? (itemStyle.opacity = pieData[i].itemStyle.opacity)
+        : null;
+      seriesItem.itemStyle = itemStyle;
+    }
+    series.push(seriesItem);
+  }
+  // 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,
+  // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。
+  const colorMap = {
+    生命通道监控点位: "#D5C307",
+    电气火灾监测点位: "#01ADEF",
+    水压检测点位: "#12A647",
+    火灾报警主机监测点位: "#caf869",
+    消防监控室人员离岗检测点位: "#88ffc6",
+  };
+  for (let i = 0; i < series.length; i += 1) {
+    endValue = startValue + series[i].pieData.value;
+    series[i].pieData.startRatio = startValue / sumValue;
+    series[i].pieData.endRatio = endValue / sumValue;
+    series[i].parametricEquation = getParametricEquation(
+      series[i].pieData.startRatio,
+      series[i].pieData.endRatio,
+      false,
+      false,
+      k,
+      // ,使除了第一个之外的值都是10
+      series[i].pieData.value
+    );
+    startValue = endValue;
+    legendData.push(series[i].name);
+
+    // 判断增加 label 效果 @20210613
+    if (pieData[i].label && pieData[i].label.show) {
+      let labelRadian =
+        (series[i].pieData.startRatio + series[i].pieData.endRatio) * Math.PI;
+      labelSeries.data.push({
+        name: series[i].name,
+        value: [
+          Math.cos(labelRadian),
+          Math.sin(labelRadian),
+          1.2,
+          series[i].pieData.value,
+        ],
+        itemStyle: {
+          opacity: 1
+        },
+      });
+    }
+  }
+
+  let colors = [];
+  if (labelSeries.data && labelSeries.data.length > 0) {
+	colors = labelSeries.data.map(p => {
+		return colorMap[p.name]
 	})
-
-	onMounted(() => {
-		initChart()
-	});
-
-	defineExpose({
-		legendToggleSelect(name) {
-			chart.dispatchAction({
-				type: "legendToggleSelect",
-				// 图例名称
-				name: name,
-			});
-		},
-	});
-
-	// 生成扇形的曲面参数方程
-	function getParametricEquation(
-		startRatio,
-		endRatio,
-		isSelected,
-		isHovered,
-		k,
-		h
-	) {
-		// 计算
-		const midRatio = (startRatio + endRatio) / 2;
-		const startRadian = startRatio * Math.PI * 2;
-		const endRadian = endRatio * Math.PI * 2;
-		const midRadian = midRatio * Math.PI * 2;
-
-		// 如果只有一个扇形,则不实现选中效果。
-		if (startRatio === 0 && endRatio === 1) {
-			// eslint-disable-next-line no-param-reassign
-			isSelected = false;
-		}
-
-		// 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
-		// eslint-disable-next-line no-param-reassign
-		k = typeof k !== "undefined" ? k : 1 / 3;
-
-		// 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
-		const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
-		const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
-
-		// 计算高亮效果的放大比例(未高亮,则比例为 1)
-		const hoverRate = isHovered ? 1.05 : 1;
-
-		// 返回曲面参数方程
-		return {
-			u: {
-				min: -Math.PI,
-				max: Math.PI * 3,
-				step: Math.PI / 32,
-			},
-
-			v: {
-				min: 0,
-				max: Math.PI * 2,
-				step: Math.PI / 20,
-			},
-
-			x(u, v) {
-				if (u < startRadian) {
-					return (
-						offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
-					);
-				}
-				if (u > endRadian) {
-					return (
-						offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
-					);
-				}
-				return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
-			},
-
-			y(u, v) {
-				if (u < startRadian) {
-					return (
-						offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
-					);
-				}
-				if (u > endRadian) {
-					return (
-						offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
-					);
-				}
-				return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
-			},
-
-			z(u, v) {
-				if (u < -Math.PI * 0.5) {
-					return Math.sin(u);
-				}
-				if (u > Math.PI * 2.5) {
-					return Math.sin(u);
-				}
-				return Math.sin(v) > 0 ? 1 : -1;
-			},
-		};
-	}
-	// 生成模拟 3D 饼图的配置项
-	function getPie3D(pieData, internalDiameterRatio) {
-		const series = [];
-		// 总和
-		let sumValue = 0;
-		let startValue = 0;
-		let endValue = 0;
-		const legendData = [];
-		const k =
-			typeof internalDiameterRatio !== "undefined" ?
-			(1 - internalDiameterRatio) / (1 + internalDiameterRatio) :
-			1 / 3;
-
-		let labelSeries = {
-			id: 'labelSeries',
-			type: 'bar3D',
-			//zlevel:-9,
-			barSize: [0, 0],
-			data: [],
-			label: {
-				show: true,
-				formatter: function(params) {
-					return `${params.value[3]}`;
-				},
-				color: '#fff',
-				fontSize: '18px'
-			},
-		};
-		// 为每一个饼图数据,生成一个 series-surface 配置
-		for (let i = 0; i < pieData.length; i += 1) {
-			sumValue += pieData[i].value;
-			// console.log(pieData[i].name);
-			const seriesItem = {
-				name: typeof pieData[i].name === "undefined" ? `series${i}` : pieData[i].name,
-				type: "surface",
-				parametric: true,
-				wireframe: {
-					show: false,
-				},
-				pieData: pieData[i],
-				pieStatus: {
-					selected: false,
-					hovered: false,
-					k,
-				},
-				// radius: 'dataValue',
-			};
-			if (typeof pieData[i].itemStyle !== "undefined") {
-				const {
-					itemStyle
-				} = pieData[i];
-				typeof pieData[i].itemStyle.color !== "undefined" ?
-					(itemStyle.color = pieData[i].itemStyle.color) :
-					null;
-				typeof pieData[i].itemStyle.opacity !== "undefined" ?
-					(itemStyle.opacity = pieData[i].itemStyle.opacity) :
-					null;
-				seriesItem.itemStyle = itemStyle;
-			}
-			series.push(seriesItem);
-		}
-		// 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,
-		// 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。
-		for (let i = 0; i < series.length; i += 1) {
-			endValue = startValue + series[i].pieData.value;
-			series[i].pieData.startRatio = startValue / sumValue;
-			series[i].pieData.endRatio = endValue / sumValue;
-			series[i].parametricEquation = getParametricEquation(
-				series[i].pieData.startRatio,
-				series[i].pieData.endRatio,
-				false,
-				false,
-				k,
-				// ,使除了第一个之外的值都是10
-				series[i].pieData.value
-			);
-			startValue = endValue;
-			legendData.push(series[i].name);
-			// 判断增加 label 效果 @20210613
-			if (pieData[i].label && pieData[i].label.show) {
-				let labelRadian = (series[i].pieData.startRatio + series[i].pieData.endRatio) * Math.PI;
-				labelSeries.data.push({
-					name: series[i].name,
-					value: [Math.cos(labelRadian), Math.sin(labelRadian), 1.2, series[i].pieData.value],
-					itemStyle: {
-						opacity: 1,
-					},
-				});
-			}
-		}
-		// 将 labelSeries 添加进去 @20210613
-		series.push(labelSeries);
-		// 准备待返回的配置项,把准备好的 legendData、series 传入。
-		const option = {
-			color: ["#D5C307", "#01ADEF", "#12A647", "#caf869", "#88ffc6"],
-			legend: {
-				top: "200%",
-			},
-			tooltip: {
-				formatter: (params) => {
-					if (params.seriesName !== "mouseoutSeries") {
-						return `${
+  }
+  // 将 labelSeries 添加进去 @20210613
+  series.push(labelSeries);
+  // 准备待返回的配置项,把准备好的 legendData、series 传入。
+  const option = {
+    color: colors,
+    legend: {
+      top: "200%",
+    },
+    tooltip: {
+      formatter: (params) => {
+        if (params.seriesName !== "mouseoutSeries") {
+          return `${
             params.seriesName
           }<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
             params.color
           };"></span>${option.series[params.seriesIndex].pieData.value}`;
-					}
-					return "";
-				},
-				extraCssText: "z-index: 1000;",
-				backgroundColor: "#02809a",
-				borderColor: "rgba(0,213,255, .6)",
-				textStyle: {
-					color: "#fff",
-				},
-			},
-			xAxis3D: {
-				min: -1,
-				max: 1,
-			},
-			yAxis3D: {
-				min: -1,
-				max: 1,
-			},
-			zAxis3D: {
-				min: -1,
-				max: "dataMax",
-			},
-			grid3D: {
-				show: false,
-				boxHeight: 25,
-				top: "-17%",
-				left: "0",
-				viewControl: {
-					// 3d效果可以放大、旋转等,请自己去查看官方配置
-					alpha: 25,
-					beta: 70, //旋转角度
-					rotateSensitivity: 1,
-					zoomSensitivity: 0,
-					panSensitivity: 0,
-					autoRotate: true,
-					distance: 210,
-				},
-				// 后处理特效可以为画面添加高光、景深、环境光遮蔽(SSAO)、调色等效果。可以让整个画面更富有质感。
-				postEffect: {
-					// 配置这项会出现锯齿,请自己去查看官方配置有办法解决
-					enable: false,
-					bloom: {
-						enable: true,
-						bloomIntensity: 0.1,
-					},
-					SSAO: {
-						enable: true,
-						quality: "medium",
-						radius: 0,
-					},
-				},
-			},
-			series,
-		};
-		return option;
-	}
+        }
+        return "";
+      },
+      extraCssText: "z-index: 1000;",
+      backgroundColor: "#02809a",
+      borderColor: "rgba(0,213,255, .6)",
+      textStyle: {
+        color: "#fff",
+      },
+    },
+    xAxis3D: {
+      min: -1,
+      max: 1,
+    },
+    yAxis3D: {
+      min: -1,
+      max: 1,
+    },
+    zAxis3D: {
+      min: -1,
+      max: "dataMax",
+    },
+    grid3D: {
+      show: false,
+      boxHeight: 25,
+      top: "-17%",
+      left: "0",
+      viewControl: {
+        // 3d效果可以放大、旋转等,请自己去查看官方配置
+        alpha: 25,
+        beta: 70, //旋转角度
+        rotateSensitivity: 1,
+        zoomSensitivity: 0,
+        panSensitivity: 0,
+        autoRotate: true,
+        distance: 210,
+      },
+      // 后处理特效可以为画面添加高光、景深、环境光遮蔽(SSAO)、调色等效果。可以让整个画面更富有质感。
+      postEffect: {
+        // 配置这项会出现锯齿,请自己去查看官方配置有办法解决
+        enable: false,
+        bloom: {
+          enable: true,
+          bloomIntensity: 0.1,
+        },
+        SSAO: {
+          enable: true,
+          quality: "medium",
+          radius: 0,
+        },
+      },
+    },
+    series,
+  };
+  return option;
+}
 </script>
 
 <template>
-	<div class="container">
-		<div ref="pieChart3d" class="chart"></div>
-	</div>
+  <div class="container">
+    <div ref="pieChart3d" class="chart"></div>
+    <div class="legend">
+      <div class="item green">
+        <div class="dot"></div>
+        在线
+      </div>
+      <div class="item red">
+        <div class="dot"></div>
+        告警
+      </div>
+    </div>
+  </div>
 </template>
 
 <style scoped lang="less">
-	.container {
-		width: 443px;
-		height: 130px;
-		position: relative;
-	}
-
-	.container::after {
-		content: "";
-		position: absolute;
-		width: 150px;
-		height: 68px;
-		background: url("../assets/images/1.png") no-repeat;
-		background-size: 100% 100%;
-		bottom: -2px;
-		left: 50%;
-		transform: translateX(-50%);
-	}
-
-	.container::before {
-		content: attr(data-num);
-		position: absolute;
-		font-size: 18px;
-		font-family: YouSheBiaoTiHei;
-		color: #ffffff;
-		line-height: 42px;
-		text-shadow: 0px 2px 6px rgba(0, 0, 0, 0.5);
-		left: 50%;
-		transform: translate(-50%);
-		top: 30%;
-	}
-
-	.chart {
-		width: 440px;
-		height: 100%;
-		position: relative;
-		z-index: 1;
-	}
+.container {
+  width: 443px;
+  height: 130px;
+  position: relative;
+
+  .legend {
+    width: 50px;
+    height: 50px;
+    position: absolute;
+    right: 42px;
+    bottom: 30px;
+    .item {
+      width: 100%;
+      height: 22px;
+      margin-bottom: 2px;
+      display: flex;
+
+      .dot {
+        width: 12px;
+        height: 12px;
+        border-radius: 100%;
+        margin-right: 10px;
+      }
+
+      &.green .dot {
+        background-color: #15ff2d;
+      }
+
+      &.red .dot {
+        background-color: #f06040;
+      }
+    }
+  }
+}
+
+.container::after {
+  content: "";
+  position: absolute;
+  width: 150px;
+  height: 68px;
+  background: url("../assets/images/1.png") no-repeat;
+  background-size: 100% 100%;
+  bottom: -2px;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.container::before {
+  content: attr(data-num);
+  position: absolute;
+  font-size: 18px;
+  font-family: YouSheBiaoTiHei;
+  color: #ffffff;
+  line-height: 42px;
+  text-shadow: 0px 2px 6px rgba(0, 0, 0, 0.5);
+  left: 50%;
+  transform: translate(-50%);
+  top: 30%;
+}
+
+.chart {
+  width: 440px;
+  height: 100%;
+  position: relative;
+  z-index: 1;
+}
 </style>

+ 102 - 106
app/src/views/Detail/components/BuildingInfo.vue

@@ -52,7 +52,7 @@
         <el-row class="row">
           <el-col :span="8">
             <span>建筑分类:</span>
-            <p style="width: 50%;" :title="detail.jzdx">{{ detail.jzdx }}</p>
+            <p style="width: 50%" :title="detail.jzdx">{{ detail.jzdx }}</p>
           </el-col>
           <el-col :span="16">
             <span>使用功能:</span>
@@ -62,69 +62,11 @@
         <el-row class="row">
           <el-col :span="24">
             <span>消防设施:</span>
-            <p :title="detail.xffssList">{{ detail.xfssList || '暂无消防设施' }}</p>
+            <p :title="detail.xffssList">
+              {{ detail.xfssList || "暂无消防设施" }}
+            </p>
           </el-col>
         </el-row>
-        <!-- <ul>
-          <li>
-            <span>建筑名称:</span>
-            <p>{{ detail.gcjzmc }}</p>
-          </li>
-          <li>
-            <span>详细地址:</span>
-            <p>{{ detail.xxdz }}</p>
-          </li>
-          <li>
-            <span>建成年代:</span>
-            <p>{{ detail.jcnd }}</p>
-          </li>
-          <li>
-            <span>区县:</span>
-            <p>{{ detail.qx }}</p>
-          </li>
-          <li>
-            <span>街镇:</span>
-            <p>{{ detail.xzjd }}</p>
-          </li>
-          <li>
-            <span>重点治理标签:</span>
-            <p>{{ detail.jzlb }}</p>
-          </li>
-          <li>
-            <span>建筑内使用功能:</span>
-            <p>{{ detail.jznsygn }}</p>
-          </li>
-        </ul>
-        <ul>
-          <li>
-            <span>建筑楼层:</span>
-            <p>{{ detail.dslc }}</p>
-          </li>
-          <li>
-            <span>使用功能:</span>
-            <p>{{ detail.jznsygn }}</p>
-          </li>
-          <li>
-            <span>建筑面积:</span>
-            <p>{{ detail.jzmj }}m²</p>
-          </li>
-          <li>
-            <span>小区:</span>
-            <p>{{ detail.xq }}</p>
-          </li>
-          <li>
-            <span>高度:</span>
-            <p>{{ detail.gd }}m</p>
-          </li>
-          <li>
-            <span>建筑分类:</span>
-            <p>{{ detail.jzdx }}</p>
-          </li>
-          <li>
-            <span>消防设施:</span>
-            <p>{{ xfssList }}</p>
-          </li>
-        </ul> -->
       </div>
       <!-- <div class="maintenance" v-if="detail">
         <span class="unit-info">维保单位:</span>
@@ -139,59 +81,88 @@
         <img src="../../../assets/images/Rectangle 3726.png" alt="" />
         <img src="../../../assets/images/Rectangle 3728.png" alt="" />
         <img src="../../../assets/images/Rectangle 3728.png" alt="" /> -->
-
-        <el-image
-          style="width: 75px; height: 51px; margin-right: 29px"
-          :src="detail.jzzp1"
-          :preview-src-list="srcList"
-          v-if="detail.jzzp1"
-        >
-        </el-image>
-        <el-image
-          style="width: 75px; height: 51px; margin-right: 29px"
-          :src="detail.jzzp2"
-          :preview-src-list="srcList"
-          v-if="detail.jzzp2"
-        >
-        </el-image>
-        <el-image
-          style="width: 75px; height: 51px; margin-right: 29px"
-          :src="detail.jzzp3"
-          :preview-src-list="srcList"
-          v-if="detail.jzzp3"
-        >
-        </el-image>
-        <el-image
-          style="width: 75px; height: 51px; margin-right: 29px"
-          :src="detail.jzzp4"
-          :preview-src-list="srcList"
-          v-if="detail.jzzp4"
-        >
-        </el-image>
-        <el-image
-          style="width: 75px; height: 51px; margin-right: 29px"
-          :src="detail.jzzp5"
-          :preview-src-list="srcList"
-          v-if="detail.jzzp5"
+        <el-carousel
+          trigger="click"
+          height="45px"
+          :interval="3000"
+          autoplay
+          indicator-position="outside"
         >
-        </el-image>
+          <el-carousel-item
+            v-for="i in itemCount"
+            :key="i"
+            style="width: 443px"
+          >
+            <div class="roww">
+              <div
+                v-for="j in 5"
+                :key="j"
+                style="width: 75px; height: 51px; margin-right: 10px"
+              >
+                <template v-if="(i - 1) * 5 + j < files.length">
+                  <el-image
+                    style="width: 75px; height: 51px; margin-right: 10px"
+                    :src="files[(i - 1) * 5 + j].url"
+                    :preview-src-list="srcList"
+                    v-if="files[(i - 1) * 5 + j].name.indexOf('.pdf') < 0"
+                  >
+                  </el-image>
+                  <a :href="files[(i - 1) * 5 + j].url" target="_blank" style="width: 75px; height: 51px; display: flex;">
+                    <img
+                      src="../../../assets/images/pdf.png"
+                      style="width: 75px; height: 51px; margin-right: 29px"
+                    />
+                  </a>
+                </template>
+
+                <!-- <el-image
+                  style="width: 75px; height: 51px; margin-right: 29px"
+                  :src="files[(i - 1) * 5 + j].url"
+                  :preview-src-list="srcList"
+                  v-if="files[(i - 1) * 5 + j].name.indexOf('.pdf') < 0"
+                >
+                </el-image>
+                <span v-else>{{ files[(i - 1) * 5 + j].name }}</span> -->
+              </div>
+            </div>
+
+            <!-- <div v-for="j in 5" :key="j">
+              <el-image
+                style="width: 75px; height: 51px; margin-right: 29px"
+                :src="files[(i - 1) * 5 + j].url"
+                :preview-src-list="srcList"
+                v-if="files[(i - 1) * 5 + j].name.indexOf('.pdf') < 0"
+              >
+              </el-image>
+              <span v-else>{{ files[(i - 1) * 5 + j].name }}</span>
+            </div> -->
+          </el-carousel-item>
+        </el-carousel>
       </div>
     </div>
   </div>
 </template>
 
 <script>
-import { getXfss } from "@/api/detail.js";
+import { getXfss, getFile } from "@/api/detail.js";
 
 export default {
   data() {
     return {
       srcList: [],
       xfssList: null,
+      files: [],
+      itemCount: 0,
     };
   },
   props: ["detail"],
   methods: {
+    getFile(i, j) {
+      const no = (i - 1) * 5 + j;
+      if (no < files.length) {
+        return;
+      }
+    },
     getXfsss() {
       getXfss({
         id: this.detail.id,
@@ -214,16 +185,29 @@ export default {
 
       return null;
     },
+    getFiles() {
+      getFile({ jzid: this.detail.id, ywid: "" }).then((res) => {
+        const files = [];
+        if (res.data.data && res.data.data.length > 0) {
+          res.data.data.forEach((p) => {
+            files.push({
+              url: `http://183.66.101.53:8787/images/${this.detail.id}/${p.fjlj}`,
+              name: p.fjmc,
+            });
+          });
+        }
+        this.files = files;
+        this.itemCount = Math.ceil(files.length / 5);
+        console.log(this.itemCount);
+        this.srcList = files
+          .filter((p) => p.name.indexOf(".pdf") < 0)
+          .map((p) => p.url);
+      });
+    },
   },
   created() {
-    this.srcList = [
-      this.detail.jzzp1,
-      this.detail.jzzp2,
-      this.detail.jzzp3,
-      this.detail.jzzp4,
-      this.detail.jzzp5,
-    ];
     this.getXfsss();
+    this.getFiles();
   },
 };
 </script>
@@ -275,14 +259,20 @@ export default {
   color: #78c3cd;
   img {
     display: inline-block;
-    margin: 10px 5px;
     width: 75px;
     height: 57px;
   }
   .accessory-img {
     display: flex;
+    height: 51px;
+    overflow: hidden;
   }
 }
+
+::v-deep(.accessory-img .el-carousel) {
+  width: 443px;
+  overflow: hidden;
+}
 .title {
   font-family: "Abel";
   font-style: normal;
@@ -312,4 +302,10 @@ export default {
   box-sizing: border-box;
   height: 24px;
 }
+.roww {
+  display: flex;
+}
+::v-deep(.el-carousel__arrow) {
+  display: none !important;
+}
 </style>

+ 48 - 37
app/src/views/Detail/components/GementUnit.vue

@@ -9,36 +9,36 @@
             <p class="g" :title="detail.xfaqglxs">{{ detail.xfaqglxs }}</p>
           </el-col>
         </el-row>
-          <el-row class="row">
-            <el-col :span="24">
-              <span>管理单位:</span>
-              <p class="g" :title="gldw.dwmc" v-if="gldw">{{ gldw.dwmc }}</p>
-            </el-col>
-          </el-row>
-          <el-row class="row">
-            <el-col :span="24">
-              <span>消防安全责任人/电话:</span>
-              <p class="g" :title="gldw.xfaqfzr" v-if="gldw">
-                {{ gldw.xfaqfzr }}/{{ gldw.xfaqfzrsjh }}
-              </p>
-            </el-col>
-          </el-row>
-          <el-row class="row">
-            <el-col :span="24">
-              <span>消防安全管理人/电话:</span>
-              <p class="g" :title="gldw.xfaqgly" v-if="gldw">
-                {{ gldw.xfaqgly }}/{{ gldw.xfaqglysjh }}
-              </p>
-            </el-col>
-          </el-row>
-          <el-row class="row">
-            <el-col :span="24">
-              <span>消防安全联系人/电话:</span>
-              <p class="g" :title="gldw.xfaqlxrdh" v-if="gldw">
-                {{ gldw.xfaqlxrxm }}/{{ gldw.xfaqlxrdh }}
-              </p>
-            </el-col>
-          </el-row>
+        <el-row class="row">
+          <el-col :span="24">
+            <span>管理单位:</span>
+            <p class="g" :title="gldw.dwmc" v-if="gldw">{{ gldw.dwmc }}</p>
+          </el-col>
+        </el-row>
+        <el-row class="row">
+          <el-col :span="24">
+            <span>消防安全责任人/电话:</span>
+            <p class="g" :title="gldw.xfaqfzr" v-if="gldw && gldw.xfaqfzr">
+              {{ gldw.xfaqfzr }}/{{ gldw.xfaqfzrsjh }}
+            </p>
+          </el-col>
+        </el-row>
+        <el-row class="row">
+          <el-col :span="24">
+            <span>消防安全管理人/电话:</span>
+            <p class="g" :title="gldw.xfaqgly" v-if="gldw && gldw.xfaqgly">
+              {{ gldw.xfaqgly }}/{{ gldw.xfaqglysjh }}
+            </p>
+          </el-col>
+        </el-row>
+        <el-row class="row">
+          <el-col :span="24">
+            <span>消防安全联系人/电话:</span>
+            <p class="g" :title="gldw.xfaqlxrdh" v-if="gldw && gldw.xfaqlxrxm">
+              {{ gldw.xfaqlxrxm }}/{{ gldw.xfaqlxrdh }}
+            </p>
+          </el-col>
+        </el-row>
       </div>
 
       <div class="building-info" v-if="detail" style="margin-top: 11px">
@@ -57,13 +57,17 @@
         <el-row class="row">
           <el-col :span="24">
             <span>负责人/电话:</span>
-            <p class="g" :title="detail.wbdwfzr + '/' + detail.wbdwfzrdh">{{ detail.wbdwfzr + '/' + detail.wbdwfzrdh }}</p>
+            <p class="g" :title="detail.wbdwfzr + '/' + detail.wbdwfzrdh">
+              {{ detail.wbdwfzr + "/" + detail.wbdwfzrdh }}
+            </p>
           </el-col>
         </el-row>
         <el-row class="row">
           <el-col :span="24">
             <span>联系人/电话:</span>
-            <p class="g" :title="detail.wbdwlxr + '/' + detail.wbdwlxrdh">{{ detail.wbdwlxr + '/' + detail.wbdwlxrdh }}</p>
+            <p class="g" :title="detail.wbdwlxr + '/' + detail.wbdwlxrdh">
+              {{ detail.wbdwlxr + "/" + detail.wbdwlxrdh }}
+            </p>
           </el-col>
         </el-row>
       </div>
@@ -82,10 +86,14 @@
             <span class="idx">{{ index + 1 }}</span>
             <span class="in_unit" :title="item.dwmc">{{ item.dwmc }}</span>
             <span class="person">{{ item.rzdwszlc }}层</span>
-            <span class="manage"
-              >{{ item.xfaqfzr }}/{{ item.xfaqfzrsjh }} <br />
-              {{ item.xfaqgly }}/{{ item.xfaqglysjh }}</span
-            >
+            <span class="manage">
+              <span v-if="item.xfaqfzr"
+                >{{ item.xfaqfzr }}/{{ item.xfaqfzrsjh }}
+              </span>
+              <span v-if="item.xfaqgly">
+                <br />{{ item.xfaqgly }}/{{ item.xfaqglysjh }}
+              </span>
+            </span>
           </li>
         </ul>
       </div>
@@ -127,7 +135,10 @@ export default {
   },
   methods: {
     openModal() {
-      this.$emit('openModal', { name: 'gldwModal', params: { gcjzmc: this.detail.gcjzmc } });
+      this.$emit("openModal", {
+        name: "gldwModal",
+        params: { gcjzmc: this.detail.gcjzmc },
+      });
     },
     getList() {
       getRzdw({

+ 35 - 5
app/src/views/Detail/components/MaintenanceModalContent.vue

@@ -1,5 +1,6 @@
 <script>
 import { getZcqk, getJdjc, getWgpc, getWbqk } from "@/api/iot.js";
+import { getFile } from "@/api/detail.js";
 import punishmentMixin from "@/mixin/unit.js";
 import moment from "moment";
 export default {
@@ -57,8 +58,25 @@ export default {
       } else if (this.checked === 3) {
         func = getWbqk;
       }
-      func(params).then((res) => {
+      func(params).then(async (res) => {
+        // console.log(res);
+        // 获取文书
+        if (this.checked === 1 && res.data.rows && res.data.rows.length > 0) {
+          for (let i = 0; i < res.data.rows.length; i++) {
+            const p = res.data.rows[i];
+            // 获取文书附件
+            const r = await getFile({ jzid: p.jzid, ywid: p.id });
+            console.log(r);
+            if (r.data.data && r.data.data.length > 0) {
+              p.file = {
+                name: r.data.data[0].fjmc,
+                url: `https://zfjg.cq119.gov.cn/api/file/${r.data.data[0].fjid}/open`,
+              };
+            }
+          }
+        }
         this.tableData = res.data.rows;
+        console.log(this.tableData);
         this.total = res.data.total;
       });
     },
@@ -123,7 +141,7 @@ export default {
       <el-table-column
         label="巡查日期"
         width="100"
-        prop="createDate"
+        prop="stime"
       ></el-table-column>
       <el-table-column
         prop="type"
@@ -146,13 +164,13 @@ export default {
         min-width="100"
       >
         <template slot-scope="scope">
-          <span v-if="scope.row.taskFlag === 2" style="color: #23f59d"
+          <span v-if="scope.row.taskFlag === '正常'" style="color: #23f59d"
             >正常</span
           >
-          <span v-if="scope.row.taskFlag === 1" style="color: #df575b"
+          <span v-if="scope.row.taskFlag === '异常'" style="color: #df575b"
             >异常</span
           >
-          <span v-if="scope.row.taskFlag === 0" style="color: #df575b"
+          <span v-if="scope.row.taskFlag === '未检'" style="color: #df575b"
             >未检</span
           >
         </template>
@@ -192,6 +210,18 @@ export default {
         min-width="100"
       >
       </el-table-column>
+      <el-table-column
+        prop="fj"
+        label="检查文书"
+        show-overflow-tooltip
+        min-width="100"
+      >
+        <template slot-scope="scope">
+          <a v-if="scope.row.file" :href="scope.row.file.url" style="color: #ffffff;" target="_blank">{{
+            scope.row.file.name
+          }}</a>
+        </template>
+      </el-table-column>
       <el-table-column
         prop="jcjg"
         label="检查结果"

+ 113 - 88
app/src/views/Detail/components/MaintenanceSupervision.vue

@@ -9,91 +9,119 @@
       </button-group>
     </div>
     <div v-if="checked === 0">
-      <div class="row header" @click="openModal(0)">
-        <span class="time">巡查日期</span>
-        <span class="person">巡查人</span>
-        <span class="result">检查结果</span>
-      </div>
-      <ul class="item" @click="openModal(0)">
-        <li class="row" v-for="(item, index) in list1" :key="index">
-          <span class="time" :tilte="item[0]">{{ item[0] }}</span>
-          <span class="person" :tilte="item[1]">{{ item[1] }}</span>
-          <span
-            class="result"
-            :style="{
-              color: resultType(item[2]),
-            }"
-             :tilte="item[2]"
-            >{{ item[2] }}</span
-          >
-        </li>
-      </ul>
+      <template v-if="list1 && list1.length > 0">
+        <div class="row header" @click="openModal(0)">
+          <span class="time">巡查日期</span>
+          <span class="person">巡查人</span>
+          <span class="result">检查结果</span>
+        </div>
+        <ul class="item" @click="openModal(0)">
+          <li class="row" v-for="(item, index) in list1" :key="index">
+            <span class="time" :tilte="item[0]">{{ item[0] }}</span>
+            <span class="person" :tilte="item[1]">{{ item[1] }}</span>
+            <span
+              class="result"
+              :style="{
+                color: resultType(item[2]),
+              }"
+              :tilte="item[2]"
+              >{{ item[2] }}</span
+            >
+          </li>
+        </ul>
+      </template>
+      <template v-else>
+        <div class="empty">
+          <img src="../../../assets/images/null2.png" style="" />
+        </div>
+      </template>
     </div>
 
     <div v-if="checked === 1">
-      <div class="row header" @click="openModal(1)">
-        <span class="time">检查日期</span>
-         <span class="person">检查单位</span>
-        <span class="person">检查对象</span>
-        <span class="result">检查结果</span>
-      </div>
-      <ul class="item" @click="openModal(1)">
-        <li class="row" v-for="(item, index) in list2" :key="index">
-          <span class="time" :tilte="item[0]">{{ item[0] }}</span>
-          <span class="time" :tilte="item[1]">{{ item[1] }}</span>
-          <span class="person" :tilte="item[2]">{{ item[2] }}</span>
-          <span
-            class="result"
-            :style="{
-              color: resultType(item[3]),
-            }"
-             :tilte="item[3]"
-            >{{ item[3] }}</span
-          >
-        </li>
-      </ul>
+      <template v-if="list2 && list2.length > 0">
+        <div class="row header" @click="openModal(1)">
+          <span class="time">检查日期</span>
+          <span class="person">检查单位</span>
+          <span class="person">检查对象</span>
+          <span class="result">检查结果</span>
+        </div>
+        <ul class="item" @click="openModal(1)">
+          <li class="row" v-for="(item, index) in list2" :key="index">
+            <span class="time" :tilte="item[0]">{{ item[0] }}</span>
+            <span class="time" :tilte="item[1]">{{ item[1] }}</span>
+            <span class="person" :tilte="item[2]">{{ item[2] }}</span>
+            <span
+              class="result"
+              :style="{
+                color: resultType(item[3]),
+              }"
+              :tilte="item[3]"
+              >{{ item[3] }}</span
+            >
+          </li>
+        </ul>
+      </template>
+      <template v-else>
+        <div class="empty">
+          <img src="../../../assets/images/null2.png" style="" />
+        </div>
+      </template>
     </div>
     <div v-if="checked === 2">
-      <div class="row header" @click="openModal(2)">
-        <span class="time">检查日期</span>
-        <span class="person">排查人员</span>
-        <span class="result">发现隐患数</span>
-      </div>
-      <ul class="item" @click="openModal(2)">
-        <li class="row" v-for="(item, index) in list3" :key="index">
-          <span class="time" :tilte="item[0]">{{ item[0] }}</span>
-          <span class="person" :tilte="item[1]">{{ item[1] }}</span>
-          <span
-            class="result"
-            :style="{
-              color: resultType(item[2]),
-            }"
-             :tilte="item[2]"
-            >{{ item[2] }}</span
-          >
-        </li>
-      </ul>
+      <template v-if="list3 && list3.length > 0">
+        <div class="row header" @click="openModal(2)">
+          <span class="time">检查日期</span>
+          <span class="person">排查人员</span>
+          <span class="result">发现隐患数</span>
+        </div>
+        <ul class="item" @click="openModal(2)">
+          <li class="row" v-for="(item, index) in list3" :key="index">
+            <span class="time" :tilte="item[0]">{{ item[0] }}</span>
+            <span class="person" :tilte="item[1]">{{ item[1] }}</span>
+            <span
+              class="result"
+              :style="{
+                color: resultType(item[2]),
+              }"
+              :tilte="item[2]"
+              >{{ item[2] }}</span
+            >
+          </li>
+        </ul>
+      </template>
+      <template v-else>
+        <div class="empty">
+          <img src="../../../assets/images/null2.png" style="" />
+        </div>
+      </template>
     </div>
     <div v-if="checked === 3">
-      <div class="row header" @click="openModal(3)">
-        <span class="time">维保日期</span>
-        <span class="person">现场检查人</span>
-        <span class="result">维保结果</span>
-      </div>
-      <ul class="item" @click="openModal(3)">
-        <li class="row" v-for="(item, index) in list4" :key="index">
-          <span class="time" :tilte="item[0]">{{ item[0] }}</span>
-          <span class="person" :tilte="item[1]">{{ item[1] }}</span>
-          <span
-            class="result"
-            :style="{
-              color: resultType(item[2]),
-            }"
-             :tilte="item[2]"
-            >{{ item[2] }}</span
-          >
-        </li>
-      </ul>
+      <template v-if="list4 && list4.length > 0">
+        <div class="row header" @click="openModal(3)">
+          <span class="time">维保日期</span>
+          <span class="person">现场检查人</span>
+          <span class="result">维保结果</span>
+        </div>
+        <ul class="item" @click="openModal(3)">
+          <li class="row" v-for="(item, index) in list4" :key="index">
+            <span class="time" :tilte="item[0]">{{ item[0] }}</span>
+            <span class="person" :tilte="item[1]">{{ item[1] }}</span>
+            <span
+              class="result"
+              :style="{
+                color: resultType(item[2]),
+              }"
+              :tilte="item[2]"
+              >{{ item[2] }}</span
+            >
+          </li>
+        </ul>
+      </template>
+      <template v-else>
+        <div class="empty">
+          <img src="../../../assets/images/null2.png" style="" />
+        </div>
+      </template>
     </div>
   </div>
 </template>
@@ -191,15 +219,7 @@ export default {
         const list = [];
         if (res.data.rows) {
           res.data.rows.forEach((p) => {
-            let status = "";
-            if (p.taskFlag === 0) {
-              status = "未检";
-            } else if (p.taskFlag === 1) {
-              status = "不合格";
-            } else if (p.taskFlag === 2) {
-              status = "合格";
-            }
-            list.push([p.finishTime, p.userCode, status]);
+            list.push([p.stime, p.userName, p.taskFlag]);
           });
         }
         this.list1 = list;
@@ -210,7 +230,7 @@ export default {
         const list = [];
         if (res.data.rows) {
           res.data.rows.forEach((p) => {
-            list.push([p.finishTime, p.jcdw, p.bjcdwmc, p.jcjg]);
+            list.push([p.startTime, p.jcdw, p.bjcdwmc, p.jcjg]);
           });
         }
         this.list2 = list;
@@ -323,4 +343,9 @@ export default {
     }
   }
 }
+.empty {
+  display: flex;
+  justify-content: center;
+  margin-top: 30px;
+}
 </style>

+ 5 - 2
app/src/views/Detail/components/QhyyModalContent.vue

@@ -131,14 +131,14 @@ export default {
             </el-select>
           </el-form-item>
           <!-- 起火日期 -->
-          <el-form-item>
+          <el-form-item class="date-picker">
             <el-date-picker
               v-model="zqsj"
               type="datetimerange"
               range-separator="至"
               start-placeholder="开始日期"
               end-placeholder="结束日期"
-              style="width: 380px"
+              style="width: 380px; margin-top: -4px"
             >
             </el-date-picker>
           </el-form-item>
@@ -358,4 +358,7 @@ export default {
 ::v-deep(.el-date-editor .el-range__close-icon) {
   line-height: 24px !important;
 }
+::v-deep(.date-picker .el-form-item__content) {
+  margin-top: -4px;
+}
 </style>

+ 54 - 16
app/src/views/Detail/components/Risklevel.vue

@@ -1,5 +1,6 @@
 <template>
   <div class="level">
+    <div class="fxdj" :style="'background-color: ' + color">低风险</div>
     <!-- 风险等级 -->
     <div class="row">
       <div
@@ -21,11 +22,15 @@
       >
         存在隐患数:
       </div>
-      <div class="level-btn2" @click="openModal('yhModal')" style="cursor: pointer">
+      <div
+        class="level-btn2"
+        @click="openModal('yhModal')"
+        style="cursor: pointer"
+      >
         <template v-if="yhList.length > 0">
           {{ yhList.length }} <span>个</span>
         </template>
-        <span v-else>无</span>
+        <span v-else>无</span>
       </div>
     </div>
     <div class="level_bottom">
@@ -91,7 +96,11 @@
       </div>
     </div>
     <div class="hzs" @click="openModal('qhyyModal')">
-      历史火灾数: <span class="hzs-cnt">{{ hzs.length }}</span> 起
+      历史火灾数:
+      <template v-if="hzs.length > 0">
+        <span class="hzs-cnt">{{ hzs.length }}</span> 起
+      </template>
+      <span v-else class="hzs-cnt">暂无</span>
     </div>
   </div>
 </template>
@@ -106,7 +115,8 @@ export default {
       fxd: [],
       yhList: [],
       hzs: [],
-      qrcode: null
+      qrcode: null,
+      color: null
     };
   },
   props: ["detail"],
@@ -160,21 +170,30 @@ export default {
       });
 
       console.log(this.detail.fxdj);
-      let color = '';
-      if (this.detail.fxdj.indexOf('低风险') >= 0) {
-        color = '#00D957';
-      } else if (this.detail.fxjd.indexOf('一般风险') >= 0) {
-        color = '#fbff3d';
-      } else if (this.detail.fxjd.indexOf('较大风险') >= 0 || this.detail.fxjd.indexOf('较高风险') >= 0) {
-        color = '#ff833d';
-      } else if (this.detail.fxjd.indexOf('重大风险') >= 0) {
-        color = '#ff0b0b';
+      let color = "";
+      let bgColor = "";
+      if (this.detail.fxdj.indexOf("低风险") >= 0) {
+        color = "#00D957";
+        bgColor = "#00A3FF";
+      } else if (this.detail.fxjd.indexOf("一般风险") >= 0) {
+        color = "#fbff3d";
+      } else if (
+        this.detail.fxjd.indexOf("较大风险") >= 0 ||
+        this.detail.fxjd.indexOf("较高风险") >= 0
+      ) {
+        color = "#ff833d";
+        bgColor = "#ff833d";
+      } else if (this.detail.fxjd.indexOf("重大风险") >= 0) {
+        color = "#ff0b0b";
+        bgColor = "#ff0b0b";
       } else {
-        color = '#35c2ff';
+        color = "#35c2ff";
+        bgColor = "#35c2ff";
       }
+      this.color = bgColor;
       getQrcode({
         url: window.location.origin + "/h5?id=" + this.detail.id,
-        color
+        color,
       }).then((res) => {
         const data = JSON.parse(res.data.data);
         this.qrcode = data.qr_code;
@@ -190,6 +209,24 @@ export default {
 <style lang="less" scoped>
 .level {
   padding: 12px 10px;
+  position: relative;
+  .fxdj {
+    width: 161px;
+    height: 44px;
+    font-family: "Abel";
+    font-style: normal;
+    font-weight: 400;
+    font-size: 24px;
+    line-height: 24px;
+    display: flex;
+    align-items: center;
+    color: #ffffff;
+    position: absolute;
+    left: 10px;
+    top: 30px;
+    display: flex;
+    justify-content: center;
+  }
   .level-btn {
     // width: 100%;
     height: 25px;
@@ -284,6 +321,7 @@ export default {
 .row {
   display: flex;
   margin-top: 12px;
+  padding-left: 175px;
   .label {
     width: 120px;
     line-height: 24px;
@@ -342,7 +380,7 @@ export default {
   line-height: 24px;
   position: absolute;
   right: 16px;
-  top: 70px;
+  top: 20px;
   font-family: "Abel";
   font-style: normal;
   font-weight: 400;

+ 15 - 7
app/src/views/Detail/components/VideoInfo.vue

@@ -17,7 +17,10 @@
         <span>暂无视频数据</span>
       </div>
     </div>
-    <Monitor3D ref="monitor" :data="pieData" v-if="pieData" />
+    <Monitor3D ref="monitor" :data="pieData" v-if="totalZs > 0" />
+    <div v-else style="width: 440px; height: 130px">
+      <img src="../../../assets/images/null2.png" style="" />
+    </div>
     <div v-if="pieData">
       <div class="info">
         <div class="bg-num" @click="clickItem(1)">
@@ -178,6 +181,7 @@ export default {
       ],
       caremaList: [],
       pieData: null,
+      totalZs: 0,
     };
   },
   props: ["detail"],
@@ -259,8 +263,10 @@ export default {
             zx: null,
           },
         };
+        let totalZs = 0;
         if (res.data.rows) {
           res.data.rows.forEach((p) => {
+            totalZs = totalZs + p.sbzs;
             if (p.sblx.indexOf("水压") >= 0) {
               // 水压
               pieData.sy.zs += p.zxs || 0;
@@ -291,10 +297,12 @@ export default {
           });
         }
 
+        console.log(totalZs);
+        this.totalZs = totalZs;
         this.pieData = pieData;
         console.log(this.pieData);
       });
-    },
+    }
   },
   mounted() {
     this.getCaremarList();
@@ -461,11 +469,11 @@ export default {
   justify-content: center;
   align-content: center;
   .in {
-	display: flex;
-	flex-direction: column;
-	span {
-		text-align: center;
-	}
+    display: flex;
+    flex-direction: column;
+    span {
+      text-align: center;
+    }
   }
 }
 </style>

+ 1 - 21
app/src/views/Detail/index.vue

@@ -40,21 +40,6 @@
         :class="middleType === '720' ? 'map' : 'd'"
         @click="changeMiddleType"
       ></div>
-      <!-- 
-      <div style="display: flex; justify-content: space-between">
-        <border-panel
-          height="270px"
-          width="468px"
-          title="历史火灾"
-          :headerType="2"
-          style="margin-right: 8px"
-        >
-          <historical-fire :detail="detail" v-if="detail" />
-        </border-panel>
-        <border-panel height="270px" width="468px" title="隐患" :headerType="2">
-          <hidden-danger :detail="detail" v-if="detail" />
-        </border-panel>
-      </div> -->
     </div>
     <div>
       <border-panel height="521px" style="margin-bottom: 6px" title="智慧消防">
@@ -84,12 +69,7 @@
     </basic-modal>
 
     <!-- 风险问号弹窗 -->
-    <basic-modal
-      top="30px"
-      ref="whFxModal"
-      name="安全风险分级预警"
-      width="90%"
-    >
+    <basic-modal top="30px" ref="whFxModal" name="安全风险分级预警" width="90%">
       <div style="display: flex; justify-content: center">
         <img src="../../assets/images/dd-exp-fx.png" />
       </div>

+ 93 - 53
app/src/views/Iot/index.vue

@@ -170,27 +170,67 @@ export default {
         this.ztqkDwtjData = res.data.rows[0];
       });
 
-      let caremaData = [];
-      // 获取视频数据
-      const deviceParam = {
-        pageNum: 1,
-        pageSize: 100,
-        qx: this.qx === "重庆市" ? "" : this.qx,
-        zt: "在线",
-        sblx: "生命通道监测",
-      };
-      const res = await getDeviceList(deviceParam);
-      caremaData = caremaData.concat(res.data.rows);
+      let caremaData = [{
+        sbbm: '50010900581314000400',
+        sblx: '生命通道监测',
+        sbmc: '两江名居公租房A区-4号附2号-消防通道(BBXF113)',
+      }, {
+        sbbm: '50010900581314000362',
+        sblx: '生命通道监测',
+        sbmc: '两江名居公租房B区-篮球场外-消防通道(BBXF110)',
+      }, {
+        sbbm: '50010900581314000401',
+        sblx: '生命通道监测',
+        sbmc: '两江名居公租房E区-4号附10号-消防通道(BBXF117)',
+      }, {
+        sbbm: '50010900581314000371',
+        sblx: '生命通道监测',
+        sbmc: '两江名居公租房B区-3号附6号-消防通道(BBXF109)',
+      }, {
+        sbbm: '50010900581314000351',
+        sblx: '生命通道监测',
+        sbmc: '两江名居公租房D区-2号附9号外-消防通道(BBXF102)',
+      }, {
+        sbbm: '50010310001310000002',
+        sblx: '消防控制室',
+        sbmc: '协信SFC中心A栋_消防控制室_人员离岗',
+      }, {
+        sbbm: '50010310001310000001',
+        sblx: '消防控制室',
+        sbmc: '协信SFC中心B栋_消防控制室_人员离岗',
+      }, {
+        sbbm: '50010310001310000006',
+        sblx: '消防控制室',
+        sbmc: '协信SFC中心B栋_车库出口左_消防通道',
+      }, {
+        sbbm: '50010310001310000007',
+        sblx: '消防控制室',
+        sbmc: '协信SFC中心B栋_1F车库入口右_消防通道',
+      }, {
+        sbbm: '50010310001310000003',
+        sblx: '消防控制室',
+        sbmc: '协信SFC中心A栋_1F车库出口_消防通道',
+      }];
+      // // 获取视频数据
+      // const deviceParam = {
+      //   pageNum: 1,
+      //   pageSize: 100,
+      //   qx: this.qx === "重庆市" ? "" : this.qx,
+      //   zt: "在线",
+      //   sblx: "生命通道监测",
+      // };
+      // const res = await getDeviceList(deviceParam);
+      // caremaData = caremaData.concat(res.data.rows);
 
-      const deviceParam2 = {
-        pageNum: 1,
-        pageSize: 100,
-        qx: this.qx === "重庆市" ? "" : this.qx,
-        zt: "在线",
-        sblx: "消防控制室监控",
-      };
-      const res2 = await getDeviceList(deviceParam2);
-      caremaData = caremaData.concat(res2.data.rows);
+      // const deviceParam2 = {
+      //   pageNum: 1,
+      //   pageSize: 100,
+      //   qx: this.qx === "重庆市" ? "" : this.qx,
+      //   zt: "在线",
+      //   sblx: "消防控制室监控",
+      // };
+      // const res2 = await getDeviceList(deviceParam2);
+      // caremaData = caremaData.concat(res2.data.rows);
 
       // // 批量请求,获取播放地址
       // const resVideos = await getCameraUrls(caremaData.map(p => p.sbbm));
@@ -208,41 +248,41 @@ export default {
       // // 只显示有视频地址的摄像头
       // caremaData = caremaData.filter(p => p.mp4);
       console.log(caremaData);
+      this.caremaData = caremaData;
 
-      if (caremaData && caremaData.length > 0) {
-        let randoms = [];
-        //随机产生mix-max之间的一个数(避免首末概率不均,采用max+1,向下取整)
-        function randomInteger(min, max) {
-          let rand = min + Math.random() * (max + 1 - min);
-          return Math.floor(rand);
-        }
-        while (true) {
-          //定义一个变量保存是否存在
-          var isExists = false;
-          // 获取一个1–100之间的数
-          var random = randomInteger(0, caremaData.length);
-          // 判断当前随机数是否已经存在
-          //通过randoms.length来确定要判断几次
-          for (let i = 0; i < randoms.length; i++) {
-            if (random === randoms[i]) {
-              isExists = true;
-              break;
-            }
-          }
-          // 如果不存在,则添加进去
-          if (!isExists) randoms.push(random);
-          // 如果有10位随机数了,就跳出
-          if (randoms.length === 10) break;
-        }
+      // if (caremaData && caremaData.length > 0) {
+      //   let randoms = [];
+      //   //随机产生mix-max之间的一个数(避免首末概率不均,采用max+1,向下取整)
+      //   function randomInteger(min, max) {
+      //     let rand = min + Math.random() * (max + 1 - min);
+      //     return Math.floor(rand);
+      //   }
+      //   while (true) {
+      //     //定义一个变量保存是否存在
+      //     var isExists = false;
+      //     // 获取一个1–100之间的数
+      //     var random = randomInteger(0, caremaData.length);
+      //     // 判断当前随机数是否已经存在
+      //     //通过randoms.length来确定要判断几次
+      //     for (let i = 0; i < randoms.length; i++) {
+      //       if (random === randoms[i]) {
+      //         isExists = true;
+      //         break;
+      //       }
+      //     }
+      //     // 如果不存在,则添加进去
+      //     if (!isExists) randoms.push(random);
+      //     // 如果有10位随机数了,就跳出
+      //     if (randoms.length === 10) break;
+      //   }
 
-        // 随机取10个
-        const showCaremarData = caremaData.filter(
-          (p, i) => randoms.indexOf(i) >= 0
-        );
-        this.caremaData = showCaremarData;
-        this.caremaList = caremaData;
-        // console.log(this.caremaData);
-      }
+      //   // 随机取10个
+      //   const showCaremarData = caremaData.filter(
+      //     (p, i) => randoms.indexOf(i) >= 0
+      //   );
+      //   this.caremaData = showCaremarData;
+      //   this.caremaList = caremaData;
+      // }
     },
     loadIotMapData() {
       getChartMapData({