111
董国庆
2026-01-28 d435601bdd21efaa8ceef0029fafc5fe502e7788
111
4个文件已修改
301 ■■■■■ 已修改文件
screen/src/view/hiddenDanger/index.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/login/index.vue 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/projectHome/index.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/projectList/index.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/hiddenDanger/index.vue
@@ -64,6 +64,7 @@
        <!-- 整改状态 -->
        <div
          v-if="showReformedFilter"
          class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 bgcolor1 searchBox"
        >
          <el-select
@@ -649,6 +650,10 @@
      activeName: "first",
      previewVisible: false,
      previewImages: [], // 预览图片列表
      // localStorage 配置
      bigHiddenDangerConfig: null, // 重大隐患配置:1开启 2关闭
      generalHiddenDangerConfig: null, // 一般隐患配置:1开启 2关闭
    };
  },
  computed: {
@@ -678,6 +683,21 @@
    // 是否显示隐患等级筛选(安全和设备隐患显示)
    showLevelFilter() {
      return this.activeTab !== 1;
    },
    // 是否显示整改状态筛选
    showReformedFilter() {
      // activeTab: 1=重大隐患 2=安全隐患 3=设备隐患
      // bigHiddenDangerConfig: 1开启 2关闭
      // generalHiddenDangerConfig: 1开启 2关闭
      if (this.activeTab === 1) {
        // 重大隐患 tab,判断 bigHiddenDangerConfig
        return this.bigHiddenDangerConfig === 1;
      } else {
        // 安全隐患和设备隐患 tab,判断 generalHiddenDangerConfig
        return this.generalHiddenDangerConfig === 1;
      }
    },
  },
  watch: {
@@ -722,6 +742,9 @@
    },
  },
  created() {
    // 从 localStorage 读取配置
    this.loadConfigFromLocalStorage();
    // 从路由获取参数
    if (this.$route.query.activeTab) {
      this.activeTab = Number(this.$route.query.activeTab);
@@ -751,6 +774,28 @@
  },
  mounted() {},
  methods: {
    // 从 localStorage 加载配置
    loadConfigFromLocalStorage() {
      try {
        const bigHiddenDanger = localStorage.getItem('bigHiddenDanger');
        const generalHiddenDanger = localStorage.getItem('generalHiddenDanger');
        // 转换为数字类型,默认为开启(1)
        this.bigHiddenDangerConfig = bigHiddenDanger ? Number(bigHiddenDanger) : 1;
        this.generalHiddenDangerConfig = generalHiddenDanger ? Number(generalHiddenDanger) : 1;
        console.log('隐患配置加载:', {
          bigHiddenDanger: this.bigHiddenDangerConfig,
          generalHiddenDanger: this.generalHiddenDangerConfig
        });
      } catch (error) {
        console.error('加载配置失败:', error);
        // 默认都开启
        this.bigHiddenDangerConfig = 1;
        this.generalHiddenDangerConfig = 1;
      }
    },
    // 初始化下拉选项
    initOptions() {
      // 整改状态选项
screen/src/view/login/index.vue
@@ -2,11 +2,7 @@
  <div class="content">
    <div class="title">智慧工程安全监管平台</div>
    <div v-if="showLoginBox" class="form">
      <img
        src="../../assets/img/login/bgTop.png"
        style="width: 371px"
        class="h--17 mt--20"
      />
      <img src="../../assets/img/login/bgTop.png" style="width: 371px" class="h--17 mt--20" />
      <div class="titleTxt">
        <div>欢</div>
        <div>迎</div>
@@ -15,121 +11,60 @@
      </div>
      <div class="mt--64 w100 px--65">
        <div class="flex a-center py--18 pl--25 pr--74 br--16 bgcolor1">
          <img
            src="../../assets/img/login/account.png"
            class="w--29 h--29 shrink0"
          />
          <input
            v-model="form.account"
            placeholder="请输入账号"
            class="h--23 ml--20 flex1"
          />
          <img src="../../assets/img/login/account.png" class="w--29 h--29 shrink0" />
          <input v-model="form.account" placeholder="请输入账号" class="h--23 ml--20 flex1" />
        </div>
        <div class="flex a-center py--18 px--25 br--16 mt--40 bgcolor1">
          <img
            src="../../assets/img/login/password.png"
            class="w--29 h--29 shrink0"
          />
          <input
            :type="showPassword ? 'text' : 'password'"
            v-model="form.password"
            placeholder="请输入密码"
            class="h--23 ml--20 flex1"
          />
          <div
            class="w--29 h--29 flex a-center j-center cursor-pointer ml--20"
            @click="togglePassword"
          >
            <img
              v-if="showPassword"
              src="../../assets/img/login/eye-open.png"
              class="w--22 h--15 shrink0"
            />
            <img
              v-if="!showPassword"
              src="../../assets/img/login/eye-close.png"
              class="w--22 h--9 shrink0"
            />
          <img src="../../assets/img/login/password.png" class="w--29 h--29 shrink0" />
          <input :type="showPassword ? 'text' : 'password'" v-model="form.password" placeholder="请输入密码"
            class="h--23 ml--20 flex1" />
          <div class="w--29 h--29 flex a-center j-center cursor-pointer ml--20" @click="togglePassword">
            <img v-if="showPassword" src="../../assets/img/login/eye-open.png" class="w--22 h--15 shrink0" />
            <img v-if="!showPassword" src="../../assets/img/login/eye-close.png" class="w--22 h--9 shrink0" />
          </div>
        </div>
        <div class="flex a-center py--13 px--25 br--16 mt--40 bgcolor1">
          <img
            src="../../assets/img/login/code.png"
            class="w--29 h--29 shrink0"
          />
          <input
            v-model="form.captcha"
            placeholder="请输入验证码"
            class="h--23 ml--20 flex1"
          />
          <div
            class="w--95 h--38 br--4 cursor-pointer relative overflow-hidden"
            style="background-color: #fff"
            @click="onCaptchaClick"
          >
          <img src="../../assets/img/login/code.png" class="w--29 h--29 shrink0" />
          <input v-model="form.captcha" placeholder="请输入验证码" class="h--23 ml--20 flex1" />
          <div class="w--95 h--38 br--4 cursor-pointer relative overflow-hidden" style="background-color: #fff"
            @click="onCaptchaClick">
            <svg class="absolute inset-0 w-full h-full">
              <!-- 波浪线 -->
              <g stroke="#999" stroke-width="1" fill="none" opacity="0.2">
                <path
                  v-for="(wave, index) in noiseData.waves"
                  :key="'wave-' + index"
                  :d="`M 0 ${wave.y} Q 24 ${wave.y - wave.amplitude} 48 ${
                    wave.y
                  } T 96 ${wave.y}`"
                />
                <path v-for="(wave, index) in noiseData.waves" :key="'wave-' + index" :d="`M 0 ${wave.y} Q 24 ${wave.y - wave.amplitude} 48 ${wave.y
                  } T 96 ${wave.y}`" />
              </g>
              <!-- 干扰线 -->
              <g stroke="#666" stroke-width="0.5" opacity="0.3">
                <line
                  v-for="(line, index) in noiseData.lines"
                  :key="'line-' + index"
                  :x1="line.x1"
                  :y1="line.y1"
                  :x2="line.x2"
                  :y2="line.y2"
                />
                <line v-for="(line, index) in noiseData.lines" :key="'line-' + index" :x1="line.x1" :y1="line.y1"
                  :x2="line.x2" :y2="line.y2" />
              </g>
              <!-- 噪点 -->
              <g fill="#999" opacity="0.4">
                <circle
                  v-for="(dot, index) in noiseData.dots"
                  :key="'dot-' + index"
                  :cx="dot.x"
                  :cy="dot.y"
                  :r="dot.size"
                />
                <circle v-for="(dot, index) in noiseData.dots" :key="'dot-' + index" :cx="dot.x" :cy="dot.y"
                  :r="dot.size" />
              </g>
            </svg>
            <div
              class="relative z-10 flex items-center justify-center h-full"
              style="
            <div class="relative z-10 flex items-center justify-center h-full" style="
                font-family: monospace;
                font-size: 24px;
                letter-spacing: 4px;
                text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
              "
            >
              <span
                v-for="(char, index) in captchaText"
                :key="index"
                class="inline-block"
                :style="{
                  color: noiseData.charStyles[index]
                    ? noiseData.charStyles[index].color
                    : '#333',
                  transform: `rotate(${
                    noiseData.charStyles[index]
                      ? noiseData.charStyles[index].rotation
                      : 0
                  }deg) translateY(${
                    noiseData.charStyles[index]
                      ? noiseData.charStyles[index].offsetY
                      : 0
              ">
              <span v-for="(char, index) in captchaText" :key="index" class="inline-block" :style="{
                color: noiseData.charStyles[index]
                  ? noiseData.charStyles[index].color
                  : '#333',
                transform: `rotate(${noiseData.charStyles[index]
                    ? noiseData.charStyles[index].rotation
                    : 0
                  }deg) translateY(${noiseData.charStyles[index]
                    ? noiseData.charStyles[index].offsetY
                    : 0
                  }px)`,
                  display: 'inline-block',
                  margin: '0 2px',
                }"
              >
                display: 'inline-block',
                margin: '0 2px',
              }">
                {{ char }}
              </span>
            </div>
@@ -143,37 +78,19 @@
    <div v-else class="selectAcount">
      <div class="tipTitle">请选择登录账号</div>
      <div class="w100 mt--56 px--50 oa">
        <div
          v-for="item in accountList"
          :key="item.id"
        <div v-for="item in accountList" :key="item.id"
          class="flex a-center j-between py--23 px--20 border1 cursor-pointer mb--34"
          :class="{ 'active-item': selectedAccount === item.id }"
          @click="selectAccount(item)"
        >
          :class="{ 'active-item': selectedAccount === item.id }" @click="selectAccount(item)">
          <div class="fs--16 lh--16 c-fff">{{ item.name }}</div>
          <img
            v-if="selectedAccount === item.id"
            src="../../assets/img/login/active.png"
            class="w--24 h--24 shrink0"
          />
          <img
            v-else
            src="../../assets/img/login/noActive.png"
            class="w--24 h--24 shrink0"
          />
          <img v-if="selectedAccount === item.id" src="../../assets/img/login/active.png" class="w--24 h--24 shrink0" />
          <img v-else src="../../assets/img/login/noActive.png" class="w--24 h--24 shrink0" />
        </div>
      </div>
      <div class="flex a-center j-center c-fff mt--64 gap--30 fs--16 pb--51">
        <div
          class="px--59 lh--40 br--4 bgcolor2 cursor-pointer"
          @click="cancelSelect"
        >
        <div class="px--59 lh--40 br--4 bgcolor2 cursor-pointer" @click="cancelSelect">
          取消
        </div>
        <div
          class="px--59 lh--40 br--4 bgcolor3 cursor-pointer"
          @click="confirmSelect"
        >
        <div class="px--59 lh--40 br--4 bgcolor3 cursor-pointer" @click="confirmSelect">
          确定
        </div>
      </div>
@@ -213,7 +130,7 @@
  created() {
    this.generateCaptcha();
  },
  mounted() {},
  mounted() { },
  methods: {
    // 生成验证码
    generateCaptcha() {
@@ -433,7 +350,10 @@
          localStorage.setItem("clientLogo", re.logo);
          localStorage.setItem("clientId", account.id);
          localStorage.setItem("deviceTemplateId", re.deviceTemplateId);//设备模板id
        localStorage.setItem("safetyId", re.safetyId);//安全报告模板id
          localStorage.setItem("safetyId", re.safetyId);//安全报告模板id
          localStorage.setItem("bigHiddenDanger", re.bigHiddenDanger); //1开启 2关闭 重大隐患
          localStorage.setItem("generalHiddenDanger", re.generalHiddenDanger);//1开启 2关闭 一般隐患
          localStorage.setItem("commentType", re.commentType); //1模糊评价 2打分评价
          localStorage.setItem(
            "permissionProject",
            JSON.stringify(
@@ -510,12 +430,11 @@
      display: flex;
      align-items: center;
      gap: 20px;
      div {
        background: linear-gradient(
          to right,
          rgba(255, 255, 255, 0.6) 1px,
          #ffffff 100%
        );
        background: linear-gradient(to right,
            rgba(255, 255, 255, 0.6) 1px,
            #ffffff 100%);
        -webkit-background-clip: text;
        /* 使用-webkit-前缀兼容部分浏览器 */
        background-clip: text;
screen/src/view/projectHome/index.vue
@@ -306,13 +306,8 @@
      </div>
    </div>
    <!-- 项目进度详情弹窗 -->
    <CustomDialog
      title="项目进度"
      :visible.sync="progressVisible"
      width="1200px"
      @close="closeProgressDialog"
      class="progress-dialog"
    >
    <CustomDialog title="项目进度" :visible.sync="progressVisible" width="1200px" @close="closeProgressDialog"
      class="progress-dialog">
      <!-- 历史进度按钮 - 使用绝对定位放在关闭按钮旁边 -->
      <div class="history-btn-fixed" @click="toProgressHistory">
        <span>历史进度</span>
@@ -327,27 +322,13 @@
          <!-- 进度图片和视频 - 缩略图网格 -->
          <div class="progress-media-grid" v-if="progressMediaList.length > 0">
            <div
              v-for="(item, index) in progressMediaList"
              :key="index"
              class="media-thumbnail"
              :class="{ 'video-thumbnail': item.type === 'video' }"
              @click="previewProgressMedia(item)"
            >
            <div v-for="(item, index) in progressMediaList" :key="index" class="media-thumbnail"
              :class="{ 'video-thumbnail': item.type === 'video' }" @click="previewProgressMedia(item)">
              <!-- 图片缩略图 -->
              <img
                v-if="item.type === 'image'"
                :src="item.url"
                class="thumbnail-img"
                @error="handleImageError"
              />
              <img v-if="item.type === 'image'" :src="item.url" class="thumbnail-img" @error="handleImageError" />
              <!-- 视频缩略图 -->
              <video
                v-else-if="item.type === 'video'"
                :src="item.url"
                class="thumbnail-video"
                @error="handleVideoError"
              ></video>
              <video v-else-if="item.type === 'video'" :src="item.url" class="thumbnail-video"
                @error="handleVideoError"></video>
              <!-- 悬浮遮罩 -->
              <div class="thumbnail-overlay">
@@ -378,31 +359,14 @@
    </CustomDialog>
    <!-- 媒体预览弹窗 -->
    <el-dialog
      :visible.sync="previewVisible"
      width="80%"
      :show-close="true"
      @close="closePreview"
      class="media-preview-dialog"
      append-to-body
    >
    <el-dialog :visible.sync="previewVisible" width="80%" :show-close="true" @close="closePreview"
      class="media-preview-dialog" append-to-body>
      <div class="preview-content">
        <!-- 图片预览 -->
        <img
          v-if="previewType === 'image'"
          :src="previewUrl"
          class="preview-image"
          @error="handleImageError"
        />
        <img v-if="previewType === 'image'" :src="previewUrl" class="preview-image" @error="handleImageError" />
        <!-- 视频预览 -->
        <video
          v-else-if="previewType === 'video'"
          :src="previewUrl"
          class="preview-video"
          controls
          autoplay
          @error="handleVideoError"
        ></video>
        <video v-else-if="previewType === 'video'" :src="previewUrl" class="preview-video" controls autoplay
          @error="handleVideoError"></video>
      </div>
    </el-dialog>
  </div>
@@ -561,9 +525,11 @@
        const permissions = res.permissionProject ? res.permissionProject.split(",") : []
        this.permissionProject = ['1', '2', '3', '4', '5', '6', '7'] || permissions
        localStorage.setItem("permissionProject", JSON.stringify(permissions));
        localStorage.setItem('commentType', res.commentType)
        localStorage.setItem("deviceTemplateId", res.deviceTemplateId);//设备模板id
        localStorage.setItem("safetyId", res.safetyId);//安全报告模板id
        localStorage.setItem("bigHiddenDanger", res.bigHiddenDanger); //1开启 2关闭 重大隐患
        localStorage.setItem("generalHiddenDanger", res.generalHiddenDanger);//1开启 2关闭 一般隐患
        localStorage.setItem("commentType", res.commentType); //1模糊评价 2打分评价
      }).catch(err => {
        console.error('获取登录信息失败:', err)
        // 设置默认值,确保页面可以继续渲染
@@ -2756,4 +2722,3 @@
  }
}
</style>
screen/src/view/projectList/index.vue
@@ -323,7 +323,7 @@
            {{ row.score || '-' }}
          </template>
        </el-table-column>
        <el-table-column label="风险类型" min-width="120">
        <el-table-column v-if="shouldShowRiskLevel" label="风险类型" min-width="120">
          <template #default="{ row }">
            {{ formatRiskLevel(row.riskLevel) }}
          </template>
@@ -519,9 +519,17 @@
      reportLoading: false,
      showPreview: false, // 是否显示预览
      currentRow: null, // 当前选中的行数据
      // 评价类型
      commentType: localStorage.getItem("commentType") || null,
    };
  },
  computed: {},
  computed: {
    // 是否显示风险类型列(commentType 不为 2 时显示)
    shouldShowRiskLevel() {
      return this.commentType != '2';
    }
  },
  watch: {
    startTime: {
      handler(newVal) {