hejianhao
2026-01-15 36ab6797d53022346d8c03ed77ca0bbda9a9b5b5
feat(projectList): 新增项目列表页面及导航功能

添加项目列表页面,包含搜索、表格展示和分页功能
实现从首页到项目列表页的导航跳转
在头部组件中添加返回首页的点击功能
更新路由配置以支持新页面
添加相关图片资源
3个文件已添加
4个文件已修改
504 ■■■■■ 已修改文件
screen/src/App.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/back.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/down-circle@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/router/index.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/header/index.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/home/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/projectList/index.vue 470 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/App.vue
@@ -29,8 +29,7 @@
      return
    } else {
      this.$router.replace({
        path: "/home",
        // query: { managementId: localStorage.getItem("managementId") },
        path: this.$route.path,
      });
    }
  },
screen/src/assets/img/back.png
screen/src/assets/img/down-circle@2x.png
screen/src/router/index.js
@@ -19,6 +19,13 @@
      title: '首页'
    }
  },
  {
    path: '/projectList',
    component: () => import('../view/projectList/index.vue'),
    meta: {
      title: '项目列表'
    }
  },
]
const createRouter = () => new Router({
@@ -32,7 +39,7 @@
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter () {
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}
screen/src/view/header/index.vue
@@ -1,6 +1,6 @@
<template>
  <div class="txt-center h--85 w100 relative imgBg">
    <div class="flex a-center c-fff absolute adress1">
    <div @click="toHome" class="flex a-center c-fff absolute adress1 cursor-pointer">
      <img src="../../assets/img/logo.png" class="w--30 h--30 shrink0 mr--10" />
      <div class="color2 lh--30 fs--30 SHSBold">成都市简州新城投资有限公司</div>
    </div>
@@ -11,7 +11,7 @@
      <div class="txt-left fs--24 SHSBold">
        <div>{{ currentDate }}</div>
      </div>
      <img src="../../assets/img/home/iconx.png" class="w--30 h--30 ml--28"/>
      <img src="../../assets/img/home/iconx.png" class="w--30 h--30 ml--28" />
    </div>
  </div>
</template>
@@ -33,6 +33,14 @@
    }
  },
  methods: {
    toHome() {
      if (this.$route.path === "/home") {
        return;
      }
      this.$router.replace({
        path: "/home",
      });
    },
    updateDateTime() {
      const now = new Date();
      // 更新日期 (YYYY年MM月DD日)
screen/src/view/home/index.vue
@@ -153,7 +153,10 @@
                </div>
              </div>
              <div class="ml--18">
                <div class="flex a-center pl--11 pr--13 py--6 bgimg2">
                <div
                  @click="toPorjectList"
                  class="flex a-center pl--11 pr--13 py--6 bgimg2 cursor-pointer"
                >
                  <div class="c-fff fs--14 SHSR mr--29 lh--14 shrink0">
                    本月检查情况
                  </div>
@@ -435,6 +438,11 @@
    this.stopAutoScroll();
  },
  methods: {
    toPorjectList() {
      this.$router.replace({
        path: "/projectList",
      });
    },
    // 切换活动索引
    changeActiveIndex(index) {
      this.activeIndex = index;
screen/src/view/projectList/index.vue
New file
@@ -0,0 +1,470 @@
<template>
  <div>
    <HeaderBox />
    <div class="pt--35 px--20 pb--54">
      <!-- 返回 -->
      <div @click="backFun" class="flex a-center cursor-pointer">
        <img
          src="../../assets/img/back.png"
          class="w--22 h--20 shrink0 mr--13"
        />
        <div class="c-fff lh--22 fs--22 SHSBold">项目列表</div>
      </div>
      <!-- 搜索 -->
      <div class="flex a-center gap--16 mt--24 mb--20">
        <div
          class="flex a-center j-between pl--18 pr--15 h--40 relative flex1 bgcolor1 searchBox"
        >
          <el-select
            filterable
            v-model="projectId"
            placeholder="请选择项目"
            class="flex1"
          >
            <el-option
              v-for="item in [1, 2]"
              :key="item"
              :label="item"
              :value="item"
            >
            </el-option>
          </el-select>
          <img
            src="../../assets/img/down-circle@2x.png"
            class="w--15 h--16 shrink0"
          />
        </div>
        <div
          class="flex a-center j-between pl--18 pr--15 h--40 relative flex1 bgcolor1 searchBox"
        >
          <el-select
            filterable
            v-model="projectId"
            placeholder="请选择项目类型"
            class="flex1"
          >
            <el-option
              v-for="item in [1, 2]"
              :key="item"
              :label="item"
              :value="item"
            >
            </el-option>
          </el-select>
          <img
            src="../../assets/img/down-circle@2x.png"
            class="w--15 h--16 shrink0"
          />
        </div>
        <div
          class="flex a-center j-between pl--18 pr--15 h--40 relative flex1 bgcolor1 searchBox"
        >
          <el-select
            filterable
            v-model="projectId"
            placeholder="请选择项目风险"
            class="flex1"
          >
            <el-option
              v-for="item in [1, 2]"
              :key="item"
              :label="item"
              :value="item"
            >
            </el-option>
          </el-select>
          <img
            src="../../assets/img/down-circle@2x.png"
            class="w--15 h--16 shrink0"
          />
        </div>
        <div
          @click="handleClick(1)"
          class="flex a-center j-between px--20 flex1 h--40 relative bgcolor1 picker"
        >
          <el-date-picker
            v-model="dateTime"
            ref="datetime1"
            type="datetime"
            placeholder=""
          >
          </el-date-picker>
          <div
            class="absolute w100 h100 flex a-center c-fff fs--14 SHS"
            style="width: calc(100% - 20px)"
            v-if="dateTxt"
          >
            {{ dateTxt }}
          </div>
          <div
            v-else
            class="absolute w100 h100 flex a-center c-fff fs--14 SHSR"
          >
            请选择日期
          </div>
          <img
            src="../../assets/img/home/Shape@2x (6).png"
            class="w--13 h--13 shrink0"
          />
        </div>
        <div
          @click="handleClick(2)"
          class="flex a-center j-between px--20 flex1 h--40 relative bgcolor1 picker"
        >
          <el-date-picker
            v-model="dateTime"
            ref="datetime2"
            type="datetime"
            placeholder=""
          >
          </el-date-picker>
          <div
            class="absolute w100 h100 flex a-center c-fff fs--14 SHS"
            style="width: calc(100% - 20px)"
            v-if="dateTxt"
          >
            {{ dateTxt }}
          </div>
          <div
            v-else
            class="absolute w100 h100 flex a-center c-fff fs--14 SHSR"
          >
            请选择日期
          </div>
          <img
            src="../../assets/img/home/Shape@2x (6).png"
            class="w--13 h--13 shrink0"
          />
        </div>
        <div
          class="flex a-center j-between flex1 pl--20 h--40 relative bgcolor1 searchBox"
        >
          <el-select
            filterable
            v-model="projectId"
            placeholder="请输入项目名称"
            class="flex1"
          >
            <el-option
              v-for="item in [1, 2]"
              :key="item"
              :label="item"
              :value="item"
            >
            </el-option>
          </el-select>
          <div class="btn">搜索</div>
        </div>
      </div>
      <!-- 表格 -->
      <el-table
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        height="800"
        :row-class-name="getClassName"
        :header-row-class-name="'headClassName'"
      >
        <el-table-column label="项目名称" prop="projectName" />
        <el-table-column label="项目类型" prop="projectName" />
        <el-table-column label="单位集合" prop="projectName">
          <template #default="scope">
            <div class="flex j-center">
              <div
                class="w--70 lh--30 txt-center j-center bgColor2 SHSR cursor-pointer"
              >
                点击查看
              </div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="项目地址" prop="projectName" />
        <el-table-column label="本月检查情况" prop="projectName" />
        <el-table-column label="最后一次检查时间" prop="projectName" />
        <el-table-column label="本月检查风险" prop="projectName" />
        <el-table-column label="操作">
          <template #default="scope">
            <el-button type="text" class="btnColor">详情</el-button>
            <el-button type="text" class="btnColor">隐患</el-button>
            <el-button type="text" class="btnColor">报告</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        class="mt--16 txt-right"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[100, 200, 300, 400]"
        :page-size="10"
        layout="total, sizes, prev, pager, next, jumper"
        :total="400"
      >
      </el-pagination>
    </div>
  </div>
</template>
<script>
import HeaderBox from "../header/index.vue";
import moment from "moment";
export default {
  components: { HeaderBox },
  props: {},
  data() {
    return {
      dateTime: null,
      projectId: null,
      dateTxt: "",
      currentPage: 1,
    };
  },
  computed: {},
  watch: {
    dateTime: {
      handler(newVal, oldVal) {
        if (newVal) {
          this.dateTxt = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss");
        }
      },
      immediate: true,
    },
  },
  created() {},
  mounted() {},
  methods: {
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
    },
    handleClick(type) {
      this.$refs[`datetime${type}`].focus();
    },
    backFun() {
      this.$router.replace({
        path: "/home",
      });
    },
    getClassName({ row, rowIndex }) {
      if (rowIndex % 2 === 0) {
        return "oneRow";
      } else {
        return "twoRow";
      }
    },
  },
};
</script>
<style scoped lang="less">
.bgcolor1 {
  background: rgba(2, 0, 77, 0.8);
  box-shadow: inset 0px 0px 34px 0px rgba(17, 40, 255, 0.66);
  border: 2px solid #0d53b7;
}
.bgColor2 {
  background: rgba(24, 69, 135, 0.9);
}
::v-deep .el-table {
  border: 2px solid #3d7fff;
  background: #071166;
  .el-table__body tr:hover > td {
    background-color: rgba(17, 40, 255, 0.2) !important;
  }
  .headClassName {
    .el-table__cell {
      background-color: #012d94 !important;
      font-family: "Source Han Sans CN Regular";
      font-size: 12px;
      color: #00ebfc;
      font-weight: 400;
      padding: 0;
      border-bottom: none;
    }
    height: 30px !important;
  }
  .el-table__cell {
    text-align: center;
    line-height: 21px;
    border-bottom: none;
  }
  .el-table__row {
    font-size: 14px;
    color: #ffffff;
    font-family: "Source Han Sans CN Medium";
  }
  .oneRow {
    background-color: #02004d !important;
    height: 50px;
  }
  .twoRow {
    background-color: #051371 !important;
    height: 50px;
  }
}
.picker {
  ::v-deep .el-input__icon {
    display: none;
  }
  ::v-deep .el-input__inner {
    background: transparent;
    border: none;
    color: transparent;
  }
  ::v-deep .el-range-input {
    background: transparent;
    border: none;
    color: transparent;
  }
}
.searchBox {
  ::v-deep .el-input__inner {
    background: transparent;
    border: none;
    color: #fff;
    padding: 0;
  }
  ::v-deep .el-input__suffix {
    display: none;
  }
  .btn {
    position: absolute;
    top: -2px;
    right: -2px;
    background: linear-gradient(
      90deg,
      #3467d0 0%,
      #0d226a 50.35%,
      #376fe0 100%
    );
    height: 38px;
    display: flex;
    align-items: center;
    font-size: 14px;
    color: #ffffff;
    font-family: "Source Han Sans CN Medium";
    padding: 0 26px;
    border: 1px solid #307ad9;
    box-sizing: border-box;
    cursor: pointer;
  }
}
::v-deep .el-pagination {
  padding: 0;
  display: flex;
  justify-content: flex-end;
  .el-pagination__total {
    font-family: "Source Han Sans CN Regular";
    font-weight: 400;
    font-size: 14px;
    color: rgba(255, 255, 255, 0.5);
    line-height: 30px;
    margin-right: 6px;
  }
  .btn-prev,
  .btn-next {
    background: rgba(1, 123, 231, 0.2);
    color: rgba(255, 255, 255, 0.5);
    padding: 0;
    width: 18px !important;
    overflow: hidden;
  }
  .btn-prev {
    margin-left: 4px;
    margin-right: 4px;
  }
  .btn-next {
    margin-left: 4px;
    margin-right: 23px;
  }
  .el-pager {
    display: flex;
    gap: 4px;
    .number {
      font-family: "Source Han Sans CN Regular";
      line-height: 30px;
      height: 30px;
      width: 30px;
      text-align: center;
      background: rgba(1, 123, 231, 0.2);
      color: rgba(255, 255, 255, 0.5);
      font-size: 14px;
      font-weight: 400;
    }
    li {
      padding: 0;
      min-width: 0;
      flex-shrink: 0;
      background-color: transparent;
    }
    li:hover {
      background: rgba(1, 123, 231, 0.5);
    }
    .active {
      background: rgba(1, 123, 231, 0.5);
    }
    .btn-quickprev,
    .btn-quicknext {
      color: rgba(182, 217, 252, 1);
    }
  }
  .el-pagination__sizes {
    margin: 0;
    .el-input {
      margin: 0;
      .el-input__inner {
        color: #017be7;
        font-size: 12px;
        background-color: transparent;
        border: 2px solid #051371;
      }
      .el-input__icon {
        color: #017be7;
      }
    }
  }
  .el-pagination__jump {
    margin-left: 0;
    color: rgba(255, 255, 255, 0.5);
    .el-pagination__editor.el-input {
      margin: 0 6px;
      .el-input__inner {
        background-color: transparent;
        border: 2px solid #051371;
        color: rgba(255, 255, 255, 0.5);
      }
    }
  }
}
.btnColor {
  color: #00ebfc;
}
</style>