riku
2025-11-27 63d9a9c62fd34f4b48a157e0bc57dd82ee09a197
2025.11.27
已修改26个文件
已删除1个文件
已添加4个文件
705 ■■■■ 文件已修改
public/~$巡查单据模板-简版.docx 补丁 | 查看 | 原始文档 | blame | 历史
public/工地巡查单据模板-简版.docx 补丁 | 查看 | 原始文档 | blame | 历史
public/现场监管场景信息导入模板.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/iconfont/iconfont.js 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SideList.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ToolBar.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/core/Header.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/core/SiderMenu.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/iconfont/IconPrinter.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/iconfont/SvgIcon.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/iconfont/index.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list-item/ItemMonitorObj.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list-item/ItemScene.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list-item/ItemSubTask.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/map/BaseMap.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/map/SceneMap.vue 190 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/composables/messageBox.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/menu.js 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/doc.js 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/index.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/marks.js 补丁 | 查看 | 原始文档 | blame | 历史
src/views/HomePage.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/config/DomainCatalog.vue 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/scene/SceneInspectFile.vue 145 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/support/JingAnNightConstruction.vue 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompMonitorObj.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompSubTaskList.vue 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompSubTaskSelect.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompTaskMap.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/~$Ѳ²éµ¥¾ÝÄ£°å-¼ò°æ.docx
Binary files differ
public/¹¤µØÑ²²éµ¥¾ÝÄ£°å-¼ò°æ.docx
Binary files differ
public/ÏÖ³¡¼à¹Ü³¡¾°ÐÅÏ¢µ¼ÈëÄ£°å.xlsx
Binary files differ
src/assets/iconfont/iconfont.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
(window._iconfont_svg_string_5068051 =
  '<svg><symbol id="icon-element-ui_printer" viewBox="0 0 1024 1024"><path d="M249.856 774.144H95.232c-6.827 0-12.117-0.341-15.872-1.024s-6.997-1.707-9.728-3.072c-5.461-3.413-9.557-7.509-12.288-12.288-1.365-2.731-2.389-5.973-3.072-9.728-0.683-3.755-1.024-9.045-1.024-15.872V375.808c0-21.163 1.195-37.205 3.584-48.128 2.389-10.923 5.632-20.139 9.728-27.648 8.875-15.701 21.163-27.989 36.864-36.864 7.509-4.096 16.725-7.339 27.648-9.728 10.923-2.389 26.965-3.584 48.128-3.584h70.656V53.248h524.288v196.608H844.8c21.163 0 37.205 1.195 48.128 3.584 10.923 2.389 20.139 5.632 27.648 9.728 15.701 8.875 27.989 21.163 36.864 36.864 4.096 7.509 7.339 16.725 9.728 27.648 2.389 10.923 3.584 26.965 3.584 48.128V732.16c0 6.827-0.341 12.117-1.024 15.872s-1.707 6.997-3.072 9.728c-3.413 5.461-7.509 9.557-12.288 12.288-2.731 1.365-5.973 2.389-9.728 3.072-3.755 0.683-9.045 1.024-15.872 1.024H774.144v196.608H249.856V774.144z m65.536-196.608v327.68h393.216v-327.68H315.392z m-65.536 131.072V512h524.288v196.608h131.072v-332.8c0-14.336-0.341-24.576-1.024-30.72s-2.219-11.093-4.608-14.848a29.687 29.687 0 0 0-9.216-9.216c-3.755-2.389-8.704-3.925-14.848-4.608-6.144-0.683-16.384-1.024-30.72-1.024H179.2c-14.336 0-24.576 0.341-30.72 1.024s-11.093 2.219-14.848 4.608a29.687 29.687 0 0 0-9.216 9.216c-2.389 3.755-3.925 8.704-4.608 14.848-0.683 6.144-1.024 16.384-1.024 30.72v332.8h131.072z m65.536-458.752h393.216V118.784H315.392v131.072z m-65.536 131.072h65.536v65.536h-65.536v-65.536z m131.072 0h65.536v65.536h-65.536v-65.536z"  ></path></symbol></svg>'),
  ((n) => {
    var e = (t = (t = document.getElementsByTagName('script'))[
        t.length - 1
      ]).getAttribute('data-injectcss'),
      t = t.getAttribute('data-disable-injectsvg');
    if (!t) {
      var i,
        o,
        c,
        s,
        d,
        a = function (e, t) {
          t.parentNode.insertBefore(e, t);
        };
      if (e && !n.__iconfont__svg__cssinject__) {
        n.__iconfont__svg__cssinject__ = !0;
        try {
          document.write(
            '<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>'
          );
        } catch (e) {
          console && console.log(e);
        }
      }
      (i = function () {
        var e,
          t = document.createElement('div');
        (t.innerHTML = n._iconfont_svg_string_5068051),
          (t = t.getElementsByTagName('svg')[0]) &&
            (t.setAttribute('aria-hidden', 'true'),
            (t.style.position = 'absolute'),
            (t.style.width = 0),
            (t.style.height = 0),
            (t.style.overflow = 'hidden'),
            (t = t),
            (e = document.body).firstChild
              ? a(t, e.firstChild)
              : e.appendChild(t));
      }),
        document.addEventListener
          ? ~['complete', 'loaded', 'interactive'].indexOf(document.readyState)
            ? setTimeout(i, 0)
            : ((o = function () {
                document.removeEventListener('DOMContentLoaded', o, !1), i();
              }),
              document.addEventListener('DOMContentLoaded', o, !1))
          : document.attachEvent &&
            ((c = i),
            (s = n.document),
            (d = !1),
            l(),
            (s.onreadystatechange = function () {
              'complete' == s.readyState &&
                ((s.onreadystatechange = null), r());
            }));
    }
    function r() {
      d || ((d = !0), c());
    }
    function l() {
      try {
        s.documentElement.doScroll('left');
      } catch (e) {
        return void setTimeout(l, 50);
      }
      r();
    }
  })(window);
src/components.d.ts
@@ -14,12 +14,14 @@
    CompQuickSet: typeof import('./components/search-option/CompQuickSet.vue')['default']
    Content: typeof import('./components/core/Content.vue')['default']
    ElAffix: typeof import('element-plus/es')['ElAffix']
    ElAlert: typeof import('element-plus/es')['ElAlert']
    ElAside: typeof import('element-plus/es')['ElAside']
    ElAvatar: typeof import('element-plus/es')['ElAvatar']
    ElBadge: typeof import('element-plus/es')['ElBadge']
    ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
    ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
    ElButton: typeof import('element-plus/es')['ElButton']
    ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
    ElCalendar: typeof import('element-plus/es')['ElCalendar']
    ElCard: typeof import('element-plus/es')['ElCard']
    ElCascader: typeof import('element-plus/es')['ElCascader']
@@ -36,6 +38,9 @@
    ElDialog: typeof import('element-plus/es')['ElDialog']
    ElDivider: typeof import('element-plus/es')['ElDivider']
    ElDrawer: typeof import('element-plus/es')['ElDrawer']
    ElDropdown: typeof import('element-plus/es')['ElDropdown']
    ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
    ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
    ElEmpty: typeof import('element-plus/es')['ElEmpty']
    ElForm: typeof import('element-plus/es')['ElForm']
    ElFormItem: typeof import('element-plus/es')['ElFormItem']
@@ -51,9 +56,16 @@
    ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
    ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
    ElOption: typeof import('element-plus/es')['ElOption']
    ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
    ElPagination: typeof import('element-plus/es')['ElPagination']
    ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
    ElPopover: typeof import('element-plus/es')['ElPopover']
    ElRadio: typeof import('element-plus/es')['ElRadio']
    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSegmented: typeof import('element-plus/es')['ElSegmented']
    ElSelect: typeof import('element-plus/es')['ElSelect']
    ElSpace: typeof import('element-plus/es')['ElSpace']
    ElStep: typeof import('element-plus/es')['ElStep']
@@ -67,6 +79,7 @@
    ElTag: typeof import('element-plus/es')['ElTag']
    ElText: typeof import('element-plus/es')['ElText']
    ElTooltip: typeof import('element-plus/es')['ElTooltip']
    ElTransfer: typeof import('element-plus/es')['ElTransfer']
    ElTree: typeof import('element-plus/es')['ElTree']
    ElUpload: typeof import('element-plus/es')['ElUpload']
    Footer: typeof import('./components/core/Footer.vue')['default']
@@ -92,6 +105,7 @@
    FYSearchBar: typeof import('./components/search-option/FYSearchBar.vue')['default']
    FYTable: typeof import('./components/table/FYTable.vue')['default']
    Header: typeof import('./components/core/Header.vue')['default']
    IconPrinter: typeof import('./components/iconfont/IconPrinter.vue')['default']
    ItemDevice: typeof import('./components/list-item/ItemDevice.vue')['default']
    ItemMonitorObj: typeof import('./components/list-item/ItemMonitorObj.vue')['default']
    ItemScene: typeof import('./components/list-item/ItemScene.vue')['default']
@@ -104,6 +118,7 @@
    SearchBar: typeof import('./components/SearchBar.vue')['default']
    SideList: typeof import('./components/SideList.vue')['default']
    SiderMenu: typeof import('./components/core/SiderMenu.vue')['default']
    SvgIcon: typeof import('./components/iconfont/SvgIcon.vue')['default']
    ToolBar: typeof import('./components/ToolBar.vue')['default']
  }
  export interface ComponentCustomProperties {
src/components/SideList.vue
@@ -1,5 +1,5 @@
<template>
  <div style="padding-right: 10px;">
  <div style="padding-right: 10px">
    <div v-if="legend" class="state-label">
      <el-input
        v-model="filterText"
@@ -47,6 +47,7 @@
        </el-space>
      </el-tooltip>
    </div>
    <slot name="header" class="state-label"></slot>
    <el-tree
      ref="treeRef"
      class="el-tree"
src/components/ToolBar.vue
@@ -38,22 +38,11 @@
    title: String,
    descriptions: {
      type: Array,
      default: () => [
        {
          name: '',
          value: ''
        }
      ]
      default: () => []
    },
    buttons: {
      type: Array,
      default: () => [
        {
          name: '',
          color: 'primary',
          click: () => {}
        }
      ]
      default: () => []
    }
  }
};
@@ -63,7 +52,7 @@
  background-color: white;
  height: var(--height-toolbar);
  border-bottom: 1px solid var(--el-color-info-light-7);
  box-shadow: 6px 4px 4px rgba(0, 0, 0, 0.12);
  box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.12);
  margin-bottom: 4px;
}
src/components/core/Header.vue
@@ -2,9 +2,16 @@
  <el-row align="middle" class="header">
    <el-col :span="12">
      <el-space>
        <el-button @click="collapsedSider" icon="Fold" circle :class="rotateIcon" />
        <el-button
          @click="collapsedSider"
          icon="ArrowLeftBold"
          circle
          :class="rotateIcon"
        />
        <el-breadcrumb separator="/" style="white-space: nowrap">
          <el-breadcrumb-item v-for="(t, i) in navTitles" :key="i">{{ t }}</el-breadcrumb-item>
          <el-breadcrumb-item v-for="(t, i) in navTitles" :key="i">{{
            t
          }}</el-breadcrumb-item>
        </el-breadcrumb>
      </el-space>
    </el-col>
@@ -65,7 +72,7 @@
}
.rotate-icon {
  transform: rotate(-90deg);
  transform: rotate(-180deg);
}
.logout {
src/components/core/SiderMenu.vue
@@ -70,7 +70,7 @@
  props: {
    collapse: {
      type: Boolean,
      default: false
      default: true
    }
  },
  emits: ['navPage'],
@@ -97,7 +97,7 @@
      return this.sysNames[this.sysIndex].name;
    },
    menus() {
      return [MENU_FYSP, MENU_FYTZ, MENU_FYPW][this.sysIndex];
      return [MENU_FYSP(), MENU_FYTZ, MENU_FYPW][this.sysIndex];
    }
  },
  methods: {
src/components/iconfont/IconPrinter.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
<template>
  <SvgIcon
    icon-class="icon-element-ui_printer"
    color="var(--el-color-default)"
  />
</template>
src/components/iconfont/SvgIcon.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
<template>
  <svg :class="classList" aria-hidden="true">
    <use :xlink:href="iconName" :fill="color" />
  </svg>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({
  className: {
    type: String,
    default: ''
  },
  iconClass: {
    type: String,
    required: true
  },
  color: {
    type: String,
    default: '#409eff'
  },
  size: {
    type: String,
    default: '20px'
  }
});
const classList = computed(() => {
  return ['icon', props.className || ''];
});
const iconName = computed(() => {
  return `#${props.iconClass}`;
});
</script>
<style scoped>
.icon {
  /* v-bind是Vue3才支持的功能,可以将CSS的值与js的值绑定 */
  width: v-bind('props.size');
  height: v-bind('props.size');
  position: relative;
  vertical-align: -2px;
  fill: currentColor;
}
</style>
src/components/iconfont/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
/**
 * åœ¨æ­¤å¤„注册的图标组件,在全局组件中可以直接使用
 * ç”¨æ³•å’ŒelementUI中的图标组件用法相同
 */
export {default as IconPrinter} from './IconPrinter.vue';
src/components/list-item/ItemMonitorObj.vue
@@ -2,13 +2,12 @@
  <!-- <el-card shadow="hover"> -->
  <div :class="statusClass + ' wrapper'">
    <div>
      <!-- <el-text>{{ item.displayid }}、</el-text> -->
      <el-text tag="b" class="text-line-2">
        {{ item.displayid + '、' + item.sensename }}
        {{ item.displayid + '. ' + item.sensename }}
      </el-text>
    </div>
    <div>
      <el-text truncated class="w-250px" type="info">
      <el-text truncated class="w-300px" type="info">
        <el-icon><LocationInformation /></el-icon>
        {{ item.scene.location }}
      </el-text>
@@ -97,6 +96,7 @@
  width: 300px;
  height: 40px;
  display: -webkit-box;
  line-height: 20px;
  line-clamp: 2;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
src/components/list-item/ItemScene.vue
@@ -2,8 +2,7 @@
  <!-- <el-card shadow="hover"> -->
  <div class="wrapper">
    <div>
      <el-text>{{ item.index }}、</el-text>
      <el-text>{{ item.name }}</el-text>
      <el-text>{{ item.index + '. ' + item.name }}</el-text>
    </div>
    <!-- <div>
      <el-text>地址:{{ item.location }}</el-text>
src/components/list-item/ItemSubTask.vue
@@ -21,7 +21,7 @@
        <div class="text-info">
          <div class="text-label">
            <el-icon class="m-r-4" size="16"><LocationInformation /></el-icon>
            <span>任务地址:</span>
            <span>地址:</span>
          </div>
          {{ item.scenseaddress }}
        </div>
@@ -29,14 +29,14 @@
          <div class="text-label">
            <!-- <el-icon><Clock /></el-icon> -->
            <el-icon class="m-r-4" size="16"><AlarmClock /></el-icon>
            <span>任务时间:</span>
            <span>时间:</span>
          </div>
          {{ $fm.formatYMD(item.planstarttime) }}
        </div>
        <div class="text-info">
          <div class="text-label">
            <el-icon class="m-r-4" size="16"><User /></el-icon>
            ä»»åŠ¡äººå‘˜ï¼š
            äººå‘˜ï¼š
          </div>
          {{ item.executorrealtimes }}
        </div>
src/components/map/BaseMap.vue
@@ -17,7 +17,7 @@
#container {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100%;
  min-height: var(--screen-min-height);
  min-width: var(--screen-min-width);
  z-index: 0px;
@@ -33,8 +33,8 @@
  opacity: 0 !important;
}
.amap-marker-label {
  font-size: 13px;
/* .amap-marker-label {
  font-size: 14px;
  text-align: center;
  color: white;
  background-color: transparent;
@@ -42,5 +42,5 @@
  border-radius: 2px;
  border: 0px;
  padding: 4px;
}
} */
</style>
src/components/map/SceneMap.vue
@@ -1,14 +1,72 @@
<template>
  <BaseMap></BaseMap>
  <el-row class="left-top-wrap">
  <div class="wrap p-events-none">
    <el-row class="p-events-none">
    <FYOptionScene
        class="p-events-auto"
      label=""
      :allOption="true"
      :type="2"
      v-model:value="scenetype"
    ></FYOptionScene>
      <div class="p-events-auto">
    <slot name="left-top"></slot>
      </div>
  </el-row>
    <el-row
      class="p-events-none left-wrap"
      align="bottom"
      :style="leftCardWrapStyle"
    >
      <div
        ref="refLeftCard"
        v-show="leftCardShow"
        class="card-left p-events-auto"
      >
        <div><el-text size="large">场景列表</el-text></div>
        <el-scrollbar height="400px" class="scrollbar">
          <el-row
            v-for="s in selectedSceneList"
            :key="s.guid"
            justify="space-between"
            class="p-v-4 scene-item"
          >
            <el-text truncated style="width: 250px">
              {{ s.index + '、' + s.name }}
            </el-text>
            <el-space>
              <el-icon
                :color="
                  s._checked ? 'rgb(121, 187, 255)' : 'rgb(200, 201, 204)'
                "
                @click="locateTo(s)"
              >
                <LocationInformation />
              </el-icon>
              <el-icon
                class="cursor-p"
                :color="
                  s._visible ? 'rgb(121, 187, 255)' : 'rgb(200, 201, 204)'
                "
                @click="handleVisibleChange(s)"
              >
                <View />
              </el-icon>
            </el-space>
          </el-row>
        </el-scrollbar>
      </div>
      <el-button
        class="close-btn-right p-events-auto"
        type="primary"
        plain
        size="small"
        :icon="leftCardShow ? 'ArrowLeft' : 'ArrowRight'"
        @click="leftCardShow = !leftCardShow"
      ></el-button>
    </el-row>
  </div>
  <!-- <el-row class="right-wrap">
    <el-col :span="4">
      <el-button>close</el-button>
@@ -17,19 +75,9 @@
      
    </el-col>
  </el-row> -->
  <el-scrollbar class="right-wrap">
    <div v-for="s in selectedSceneList" :key="s.guid">
      <el-checkbox
        v-model="s._checked"
        :label="s.name"
        @change="handleChange(s)"
      />
      <!-- <el-text>{{ s.name }}</el-text> -->
    </div>
  </el-scrollbar>
</template>
<script setup>
import { ref, watch, computed } from 'vue';
import { ref, watch, computed, onMounted } from 'vue';
import { map, onMapMounted } from '@/utils/map/index';
import marks from '@/utils/map/marks';
import mapUtil from '@/utils/map/util';
@@ -39,6 +87,17 @@
  data: Array
});
onMounted(() => {
  // refLeftCard.value.offsetHeight;
  // leftCardWrapStyle.value = {
  //   height: refLeftCard.value.offsetHeight + 'px'
  // };
});
const refLeftCard = ref();
const leftCardShow = ref(true);
const leftCardWrapStyle = ref();
let allMarkViews = [];
let markViewList = [];
@@ -46,7 +105,7 @@
const selectedSceneList = computed(() => {
  return props.data.filter((v) => {
    v._checked = true;
    v._visible = true;
    return (
      scenetype.value == undefined ||
      scenetype.value.value == null ||
@@ -74,16 +133,25 @@
  }
});
function handleChange(scene) {
function handleVisibleChange(scene) {
  const mv = markViewList.find((v) => {
    return scene.guid == v.getExtData().guid;
  });
  if (scene._checked) {
  scene._visible = !scene._visible;
  if (scene._visible) {
    map.add(mv);
  } else {
    map.remove(mv);
  }
  // filterMarkViews();
}
function locateTo(scene) {
  const mv = markViewList.find((v) => {
    return scene.guid == v.getExtData().guid;
  });
  if (mv) {
    mapUtil.setFitView(mv);
  }
}
function createSceneMarks() {
@@ -94,28 +162,40 @@
      const mark = marks.createMarker({
        position: [d.longitude, d.latitude],
        img: sceneIcon(d.typeid),
        // label: d.name,
        label: '',
        extData: d
      });
      var timeout;
      // æ·»åŠ ç‚¹å‡»äº‹ä»¶
      mark.on('click', (ev) => {
      mark.on('mouseover', (ev) => {
        if (timeout) {
          clearTimeout(timeout);
        }
        const _mark = ev.target;
        const _extData = _mark.getExtData();
        if (_extData._show) {
          ev.target.setLabel({
            content: ''
            // direction: 'bottom'
          });
          _extData._show = false;
          ev.target.setExtData(_extData);
        } else {
          ev.target.setLabel({
            content: _extData.name
            // direction: 'bottom'
          });
          _extData._show = true;
          ev.target.setExtData(_extData);
        }
        timeout = setTimeout(() => {
          ev.target.setLabel({
            content: ''
          });
        }, 2000);
        // if (_extData._show) {
        //   ev.target.setLabel({
        //     content: ''
        //     // direction: 'bottom'
        //   });
        //   _extData._show = false;
        //   ev.target.setExtData(_extData);
        // } else {
        //   ev.target.setLabel({
        //     content: _extData.name
        //     // direction: 'bottom'
        //   });
        //   _extData._show = true;
        //   ev.target.setExtData(_extData);
        // }
      });
      allMarkViews.push(mark);
    });
@@ -142,7 +222,7 @@
    }
    markViewList = markViewList.filter((v) => {
      const _index = selectedSceneList.value.findIndex((s) => {
        return s.guid == v.getExtData().guid && s._checked;
        return s.guid == v.getExtData().guid && s._visible;
      });
      return _index != -1;
    });
@@ -169,20 +249,46 @@
}
</script>
<style scoped>
.left-top-wrap {
.wrap {
  position: absolute;
  left: 0px;
  top: 0;
  width: 100%;
  height: 100%;
}
.left-wrap {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 1px;
}
.right-wrap {
  position: absolute;
  right: 0px;
  bottom: 0;
  height: 50%;
.card-left {
  background-color: white;
  border-radius: 4px;
  padding: 2px 8px;
  max-width: 300px;
  box-shadow: var(--el-box-shadow);
  /* border-radius: 4px; */
  width: 316px;
  /* box-shadow: var(--el-box-shadow); */
  z-index: 0;
}
.scrollbar {
  padding-right: 8px;
  /* width: 300px; */
}
.close-btn-right {
  margin-left: -3px;
  height: 60px;
}
.p-events-auto {
  pointer-events: auto;
}
.p-events-none {
  pointer-events: none;
}
.scene-item {
  /* background-color: aliceblue; */
}
</style>
src/composables/messageBox.js
@@ -34,7 +34,7 @@
      }
      ElMessage({
        message: errStr,
        type: 'warning',
        type: 'error',
      });
    });
}
src/constants/menu.js
@@ -13,7 +13,7 @@
  });
}
const MENU_FYSP = [
const _MENU_FYSP = [
  // {
  //   icon: 'Search',
  //   name: '巡查审核',
@@ -164,7 +164,8 @@
      {
        path: '/fysp/config/domainCatalog',
        icon: 'List',
        name: '值域目录'
        name: '值域目录',
        debug: true
      }
    ]
  },
@@ -259,4 +260,32 @@
  }
];
const MENU_FYSP = () => {
  // æ·±æ‹·è´åŽŸå§‹èœå•æ•°ç»„ï¼Œé¿å…ä¿®æ”¹åŽŸæ•°æ®
  const menuCopy = JSON.parse(JSON.stringify(_MENU_FYSP));
  // é€’归处理菜单项
  const processMenuItem = (item) => {
    // å¦‚果当前项有children属性
    if (item.children && Array.isArray(item.children)) {
      // æ ¹æ®çŽ¯å¢ƒè¿‡æ»¤children数组
      item.children = item.children.filter(child => {
        // é€’归处理子项的children
        processMenuItem(child);
        // å¼€å‘环境保留所有项(包括debug: true的),生产环境过滤掉debug: true的项
        // æ³¨æ„ï¼šåªæœ‰è®¾ç½®äº†debug: true的项才需要在非开发环境过滤
        // å¦‚果没有debug属性,应该保留
        return import.meta.env.DEV || child.debug !== true;
      });
    }
    return item;
  };
  // å¤„理整个菜单数组
  return menuCopy.map(processMenuItem);
};
export { MENU_FYSP, MENU_FYTZ, MENU_FYPW, MENU_COMMON };
src/main.js
@@ -8,6 +8,8 @@
// import 'element-plus/dist/index.css';
import './assets/main.css';
import './assets/iconfont/iconfont.js'
import * as MyIconfont from './components/iconfont';
import { ElMessageBox, ElNotification, ElMessage } from 'element-plus';
import 'element-plus/theme-chalk/src/overlay.scss';
@@ -35,6 +37,13 @@
  app.component(key, component);
}
// å…¨å±€æ³¨å†Œè‡ªå®šä¹‰å›¾æ ‡ç»„ä»¶
for (const [key, component] of Object.entries(MyIconfont)) {
  app.component(key, component);
}
app
  .use(pinia)
  .use(router)
src/utils/doc.js
@@ -311,7 +311,7 @@
  FileSaver.saveAs(blob, zipName);
}
function print(
function print({
  ref,
  title,
  style,
@@ -320,23 +320,23 @@
  borderHeadStyle,
  gridStyle,
  css
) {
}) {
  printJS({
    printable: ref,
    header: title || null,
    type: type || 'html',
    // headerStyle:
    //   'font-size:6px;font-weight:600;text-align:center;padding:15px 0 10px 0;', //标题设置
    headerStyle:
      'font-size:6px;font-weight:600;text-align:center;padding:15px 0 10px 0;', //标题设置
    properties: jsonData || [], //json数据元
    gridHeaderStyle:
      borderHeadStyle ||
      'font-size:6px;font-weight:400;height:40px;line-height:40px;border: 1px solid #ccc;padding:3px 5px 3px 5px;text-align:center;', //json格式表头样式
    gridStyle:
      gridStyle ||
      'font-size:1px;font-weight:200;border: 1px solid #ccc;padding:3px 5px 3px 5px;text-align:center;', //json各式表哥央视
    // gridHeaderStyle:
    //   borderHeadStyle ||
    //   'font-size:6px;font-weight:400;height:40px;line-height:40px;border: 1px solid #ccc;padding:3px 5px 3px 5px;text-align:center;', //json格式表头样式
    // gridStyle:
    //   gridStyle ||
    //   'font-size:1px;font-weight:200;border: 1px solid #ccc;padding:3px 5px 3px 5px;text-align:center;', //json各式表哥央视
    scanStyles: false, //不适用默认样式
    repeatTableHeader: false, //打印json表头只显示在第一页
    style: style || `@page{size:auto;margin: 0cm 1cm 0cm 1cm;}`, //去除页眉页脚
    style: style || `@page{size:A4;margin: -1cm 0cm 0cm 0cm;}`, //去除页眉页脚
    css: css || null //css url
  });
}
src/utils/map/index.js
@@ -49,6 +49,7 @@
        e();
      });
      onMapMountedEvents = [];
      console.log('-------------------map init done');
    })
    .catch((e) => {
      console.log(e);
src/utils/map/marks.js
src/views/HomePage.vue
@@ -45,7 +45,7 @@
export default {
  data() {
    return {
      isCollapsed: false,
      isCollapsed: true,
      navTitles: [],
      headerHeight: 60,
      mainPadding: 10,
src/views/fysp/config/DomainCatalog.vue
@@ -6,9 +6,26 @@
        :items="domainCatalog"
        :loading="sideLoading"
        @item-click="chooseCatalog"
      ></SideList>
      >
        <template #header>
          <el-row justify="end">
            <el-button
              type="primary"
              icon="CirclePlusFilled"
              size="small"
              @click="handelDownload"
            >
            </el-button>
          </el-row>
        </template>
      </SideList>
    </template>
    <template #main>
      <ToolBar
        class="toolbar-sticky"
        :title="selectedCatalog?.name"
        :loading="loading"
      ></ToolBar>
      <!-- <FormCol> -->
      <el-table
        :data="domainItems"
@@ -204,12 +221,12 @@
// å–消编辑
function cancelEdit(scope) {
  scope.row._isAdd = false;
  scope.row._isEdit = false;
  if (scope.row._isAdd) {
  domainItems.value.splice(scope.$index, 1);
}
  scope.row._isAdd = false;
  scope.row._isEdit = false;
}
function _validate(row) {
  return (
src/views/fysp/scene/SceneInspectFile.vue
@@ -2,7 +2,7 @@
  <el-dialog
    :model-value="modelValue"
    @update:model-value="handleDialogChange"
    title="巡查单据下载"
    title="巡查单据下载打印"
    class="dialog-wrapper"
    v-loading="loading"
  >
@@ -43,9 +43,9 @@
                type="default"
                size="small"
                class="m-t-4"
                icon="IconPrinter"
                @click="handlePreview(item)"
              >
                é¢„览
              </el-button>
            </el-row>
          </el-checkbox>
@@ -54,17 +54,33 @@
    </el-scrollbar>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="danger" @click="cancel">取消</el-button>
        <el-button type="primary" :loading="docLoading" @click="handelDownload">
          ä¸‹è½½
        <el-button type="danger" @click="cancel" icon="CloseBold"
          >取消</el-button
        >
        <el-button
          type="primary"
          :loading="docLoading"
          icon="Download"
          :disabled="checkList.length == 0"
          @click="handelDownload"
        >
          ä¸‹è½½æ‰€é€‰
        </el-button>
        <el-button type="default" :loading="docLoading" @click="handelPrint">
          æ‰“印
        <el-button
          type="default"
          :loading="docLoading"
          :disabled="checkList.length == 0"
          @click="handlePreview()"
          icon="IconPrinter"
        >
          <el-space>
            æ‰“印所选
          </el-space>
        </el-button>
      </div>
    </template>
  </el-dialog>
  <el-dialog v-model="previewVisible" :show-close="true" fullscreen>
  <el-dialog v-model="previewVisible" :show-close="false" fullscreen>
    <template #header="{ close, titleId, titleClass }">
      <el-row justify="end">
        <el-button type="danger" @click="close" icon="CircleCloseFilled">
@@ -73,14 +89,18 @@
        <el-button
          type="primary"
          @click="handelPrint(refWord)"
          icon="PrintFilled"
          icon="IconPrinter"
        >
          æ‰“印
        </el-button>
      </el-row>
    </template>
    <div ref="refWord">
      <div
        :id="`word-preview-${i}`"
        v-for="(item, i) in previewList"
        :key="item"
      ></div>
    </div>
    <!-- <iframe ref="pdfPreview" width="100%" height="100vh" style="height: calc(100vh - 60px);"></iframe> -->
  </el-dialog>
@@ -90,7 +110,7 @@
 * åœºæ™¯å·¡æŸ¥å•据自动下载
 */
import { ref, watch } from 'vue';
import { useRouter } from "vue-router";
import { useRouter } from 'vue-router';
import {
  exportDocx,
  prepareDocxBlob,
@@ -124,6 +144,8 @@
// é¢„览对话框开关
const previewVisible = ref(false);
// é¢„览的文档
const previewList = ref([]);
watch(
  () => [props.modelValue, props.value],
@@ -236,7 +258,7 @@
// æ ¹æ®åœºæ™¯ç±»åž‹ï¼Œç”Ÿæˆå¯¹åº”çš„word文档
function generateDoc(param, callback) {
  param.map((p) => {
  param.map((p, index) => {
    let template, _param;
    switch (p.type) {
      // å·¥åœ°
@@ -253,30 +275,7 @@
        break;
    }
    prepareDocxBlob(template, _param).then((blob) => {
      callback(blob, `${_param.name}巡查单据.docx`);
    });
  });
}
function generatePdf(param, callback) {
  param.map((p) => {
    let template, _param;
    switch (p.type) {
      // å·¥åœ°
      case 1:
        template = '/工地巡查单据模板-简版.docx';
        _param = p.params;
        break;
      // é¤é¥®
      case 5:
        template = '/餐饮巡查单据模板.docx';
        _param = p.params;
        break;
      default:
        break;
    }
    preparePdf(template, _param).then((blob) => {
      callback(blob, `${_param.name}巡查单据.pdf`);
      callback(blob, `${_param.name}巡查单据.docx`, index);
    });
  });
}
@@ -298,47 +297,36 @@
// ç‚¹å‡»æ‰“印按钮操作
function handelPrint(ref) {
  if (ref) {
    print(ref);
    print({
      ref,
      // æ ¹æ®ç›®å‰ä½¿ç”¨çš„docx-preview组件,设置打印样式,主要去除多余的margin和padding,以及阴影效果
      style: `
        @page{size:A4;margin: 0 !important;padding:0 !important;}
        body {margin: 0 !important;padding:0 !important;}
        header {color: rgb(182, 182, 182);}
        footer {color: rgb(182, 182, 182);}
        .docx-wrapper {padding: 0 !important;}
        .docx {margin-bottom: 0 !important; box-shadow: none !important;}
        .docx_5 {
          display: flex;
          justify-content: space-between;
          align-items: flex-end;
  }
  // const file = filePrepare();
  // if (file) {
  //   previewDocx(file.blob, refWord.value);
  // }
      `
    });
  }
}
function handlePreview(item) {
  const param = parseParam(item);
  // é¢„览的文档,区分单独打印和打印全部
  previewList.value = item ? ['0'] : checkList.value;
  const param = item ? parseParam(item) : parseParam();
  if (param) {
    generatePdf(param, (blob, name) => {
    generateDoc(param, (blob, name, index) => {
      previewVisible.value = true;
      setTimeout(() => {
        previewDocx(blob, refWord.value);
        previewDocx(blob, document.getElementById(`word-preview-${index}`));
      }, 200);
      // blob.print()
      // blob.getBlob((buffer) => {
      //   previewDocx(buffer, refWord.value);
      // });
      // const resolved = router.resolve({
      //   path: '/fysp/scene/SceneInspectFile',
      //   query: {
      //     data: JSON.stringify(blob),
      //   }
      // });
      // window.open(resolved.href, '_blank')
      // console.log('pdf', blob);
      // blob.autoPrint();
      // // blob.save(name)
      // // ç”ŸæˆPDF的Blob对象
      // var pdfBlob = blob.output('blob');
      // setTimeout(() => {
      //   // åœ¨iframe中显示预览
      //   pdfPreview.value.src = URL.createObjectURL(pdfBlob);
      // }, 200);
    });
  }
}
@@ -363,4 +351,23 @@
:deep(.el-checkbox__label) {
  width: 100%;
}
/* æ–‡æ¡£å­—体 */
:deep(section.docx) {
  font-family: '黑体' !important;
}
/* æ–‡æ¡£æ ‡é¢˜ */
:deep(header) {
  color: rgb(182, 182, 182);
}
:deep(.docx_5) {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
}
/*  */
:deep(footer) {
  color: rgb(182, 182, 182);
}
</style>
src/views/fysp/support/JingAnNightConstruction.vue
@@ -23,7 +23,7 @@
        sortable
        prop="ncNum"
        label="编号"
        width="100"
        width="90"
      >
      </el-table-column>
      <el-table-column
@@ -31,7 +31,7 @@
        prop="ncItemName"
        label="项目名称"
        :show-overflow-tooltip="true"
        width="400"
        width="200"
      >
      </el-table-column>
      <!-- <el-table-column prop="ncItemUnit" label="业主单位" width="130" /> -->
@@ -42,7 +42,7 @@
       <el-table-column
        prop="ncFileName"
        label="夜施文件"
        width="170"
        width="186"
      >
        <template #default="{ row }">
          <el-link
@@ -51,6 +51,15 @@
            :href="row.ncUrl"
            target="_blank"
            >{{ row.ncFileName }}</el-link
          >
        </template>
      </el-table-column>
      <el-table-column prop="ncUserId" label="匹配用户">
        <template #default="{ row }">
          <el-text
            :loading="row._loading"
            :type="row._user ? 'success' : 'danger'"
            >{{ row._user ? row._user.realname : '未匹配' }}</el-text
          >
        </template>
      </el-table-column>
@@ -81,15 +90,6 @@
          {{ $fm.formatYMD(row.ncCreateTime) }}
        </template>
      </el-table-column> -->
      <el-table-column prop="ncUserId" label="匹配用户">
        <template #default="{ row }">
          <el-text
            :loading="row._loading"
            :type="row._user ? 'success' : 'danger'"
            >{{ row._user ? row._user.realname : '未匹配' }}</el-text
          >
        </template>
      </el-table-column>
      <el-table-column fixed="right" label="操作" width="80">
        <template #default="{ row }">
          <el-button
src/views/fysp/task/components/CompMonitorObj.vue
@@ -41,7 +41,7 @@
      </el-checkbox-group>
    </el-space>
    <el-scrollbar :height="height">
      <el-space wrap>
      <el-space v-if="activeData.length > 0" wrap style="padding-bottom: 200px;">
        <ItemMonitorObj v-for="obj in activeData" :key="obj.movid" :item="obj">
          <template #default="{ item }">
            <slot :item="item">
@@ -57,6 +57,7 @@
          </template>
        </ItemMonitorObj>
      </el-space>
      <el-empty v-else description="暂无记录" />
    </el-scrollbar>
  </div>
</template>
@@ -95,7 +96,7 @@
    return {
      activeName: defaultTabName,
      tabs: [],
      checkList: [0, 1, 2]
      checkList: [0]
    };
  },
  computed: {
src/views/fysp/task/components/CompSubTaskList.vue
@@ -1,19 +1,16 @@
<template>
  <el-row justify="space-between">
    <el-text>单日计划</el-text>
    <div>
    <div v-show="create && data && data.length > 0">
      <el-button
        icon="IconPrinter"
        type="success"
        size="small"
        plain
        @click="handleInspectFileDownload"
        >单据下载</el-button
        >单据打印</el-button
      >
      <el-button
        v-show="create && data && data.length > 0"
        type="success"
        size="small"
        @click="add"
      <el-button type="success" size="small" @click="add" icon="Switch"
        >任务调整</el-button
      >
    </div>
@@ -36,13 +33,15 @@
                plain
                type="primary"
                size="small"
                icon="EditPen"
                @click="edit(item)"
                >编辑</el-button
                >修改</el-button
              >
              <el-button
                :disabled="item.status != '未执行'"
                type="default"
                type="danger"
                size="small"
                icon="Delete"
                @click="remove(item)"
                >移除</el-button
              >
@@ -79,13 +78,16 @@
      @cancel="dialogVisible = false"
    ></CompSubTaskEdit>
  </el-dialog>
  <SceneInspectFile v-model="downloadDialog" :value="downloadSceneList"></SceneInspectFile>
  <SceneInspectFile
    v-model="downloadDialog"
    :value="downloadSceneList"
  ></SceneInspectFile>
</template>
<script setup>
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
import { ElMessageBox, ElNotification, ElMessage } from 'element-plus';
import CompSubTaskEdit from './CompSubTaskEdit.vue';
import SceneInspectFile from "@/views/fysp/scene/SceneInspectFile.vue";
import SceneInspectFile from '@/views/fysp/scene/SceneInspectFile.vue';
import subtaskApi from '@/api/fysp/subtaskApi';
const props = defineProps({
@@ -104,7 +106,7 @@
const activeItem = ref(null);
const data = computed(() => props.modelValue);
const downloadDialog = ref(false);
const downloadSceneList = ref([])
const downloadSceneList = ref([]);
const emit = defineEmits(['submit', 'add', 'remove', 'update:modelValue']);
@@ -154,7 +156,7 @@
});
function handleInspectFileDownload() {
  downloadSceneList.value = data.value.map(v=>v.scenseid)
  downloadDialog.value = true
  downloadSceneList.value = data.value.map((v) => v.scenseid);
  downloadDialog.value = true;
}
</script>
src/views/fysp/task/components/CompSubTaskSelect.vue
@@ -110,11 +110,9 @@
});
function submit(v, success, fail) {
  if (props.data.length == 0) {
    // ElMessage({
    //   message: '未选择监管场景',
    //   type: 'warning'
    // });
    fail('未选择监管场景');
  } else if (v.value.executor.length == 0) {
    fail('未选择执行人');
  } else {
    success();
    // å°†ä»»åŠ¡æ‰§è¡Œäººæ ¼å¼åŒ–å¹¶ä¼ é€’
@@ -174,7 +172,8 @@
  () => props.dayTask,
  (nV, oV) => {
    if (nV != oV) {
      taskApi.fetchTaskById(nV.guid).then((res) => {
      // æ ¹æ®æ—¥ä»»åŠ¡ï¼ŒèŽ·å–å¯¹åº”çš„æ€»ä»»åŠ¡ä¿¡æ¯ï¼Œå†èŽ·å–æ‰§è¡Œäººå‘˜ä¿¡æ¯
      taskApi.fetchTaskById(nV.tsGuid).then((res) => {
        getExecutors(res);
      });
    }
src/views/fysp/task/components/CompTaskMap.vue
@@ -31,6 +31,9 @@
const scenes = computed(() => {
  return props.plans
    .filter((v) => {
      if (!v.scene.longitude || !v.scene.latitude) {
        return false;
      }
      // æŒ‰ç…§ç›‘管状态筛选
      if (supervisionStatus.value) {
        switch (supervisionStatus.value.value) {
@@ -50,11 +53,6 @@
      } else {
        return true
      }
      // if (supervisionStatus.value) {
      //   supervisionStatus.value;
      // } else {
      //   return true;
      // }
    })
    .map((p) => {
      return p.scene;