董国庆
2026-01-19 0c583e51ef54a299875186ffcba6dd3308b7caaa
Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/smartBuilding
3个文件已删除
32个文件已添加
15个文件已修改
7544 ■■■■■ 已修改文件
estate-frontend-v2024/src/config/menuConfig.js 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/config/routeMap.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/check.jsx 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/clientInfo.jsx 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/dataProblem.jsx 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/forms/edit-clientParams-form.jsx 666 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/forms/edit-dataP-form.jsx 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/forms/edit-project-form.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/forms/edit-projectPermission-form.jsx 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/forms/edit-projectStatus-form.jsx 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/onDuty.jsx 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/projects.jsx 665 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/style/clientParams.less 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/common/crud-view-base.jsx 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/layout/Header/index.jsx 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/layout/Header/index.less 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/accidentMessageSetting.jsx 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/accidentTypeSetting.jsx 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/accountSetting.jsx 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/forms/edit-accidentMessage-form.jsx 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/forms/edit-accidentType-form.jsx 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/forms/edit-account-form.jsx 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/forms/reset-password-form.jsx 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/style/index.less 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/standard/forms/edit-position-form.jsx 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/standard/position.jsx 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/.gitignore 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/App.vue 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/77Combined Shape@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/89Combined Shape@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/Group@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/Rectangle 4@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/Shape@2x99.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/components/column.js 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/components/customDialog.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/components/customPagination.vue 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/components/customPreview.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/components/customTable.vue 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/components/service.js 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/components/tableModel.vue 542 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/main.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/router/index.js 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/accidentCase/detail.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/accidentCase/index.vue 351 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/equipmentList/index.vue 490 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/hiddenDanger/index.vue 669 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/home/index.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/projectList/index.vue 348 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/workList/detail.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/workList/index.vue 533 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/config/menuConfig.js
@@ -12,7 +12,7 @@
        title: "智慧大屏",
        path: "/dashboard",
        icon: "line-chart",
        permissions: ["*"]
        permissions: ["*"],
      },
      // {
      //   title: "任务日历",
@@ -20,7 +20,29 @@
      //   icon: "calendar",
      //   permissions: ["*"]
      // }
    ]
    ],
  },
  {
    title: "智慧大屏设置",
    path: "/screenSetting",
    icon: "setting",
    children: [
      {
        title: "大屏账号设置",
        path: "/screenSetting/accountSetting",
        permissions: ["*"],
      },
      {
        title: "事故分类设置",
        path: "/screenSetting/accidentTypeSetting",
        permissions: ["*"],
      },
      {
        title: "事故简讯",
        path: "/screenSetting/accidentMessageSetting",
        permissions: ["*"],
      },
    ],
  },
  {
    title: "人事管理",
@@ -30,22 +52,22 @@
      {
        title: "用户管理",
        path: "/management/userManagement",
        permissions: ["user:*"]
        permissions: ["user:*"],
      },
      {
        title: "岗位管理",
        path: "/management/roleManagement",
        permissions: ["role:*"]
        permissions: ["role:*"],
      },
      {
        title: "部门管理",
        path: "/management/departmentManagement",
        permissions: ["department:*"]
        permissions: ["department:*"],
      },
      {
        title: "车辆调度",
        path: "/management/vehicleDispatch",
        permissions: ["car:*"]
        permissions: ["car:*"],
      },
      // {
      //   title: "调度管理",
@@ -69,7 +91,7 @@
      //     // }
      //   ]
      // }
    ]
    ],
  },
  {
    title: "业务信息",
@@ -79,23 +101,23 @@
      {
        title: "委托方清单",
        path: "/business/clientInfo",
        permissions: ["client:*"]
        permissions: ["client:*"],
      },
      {
        title: "合同管理",
        path: "/business/contract",
        permissions: ["contract:*"]
        permissions: ["contract:*"],
      },
      {
        title: "项目列表",
        path: "/business/projects",
        permissions: ["project:*"]
        permissions: ["project:*"],
      },
      {
        title: "设备管理",
        path: "/business/devices",
        permissions: ["device:*"]
      }
        permissions: ["device:*"],
      },
    ],
  },
  {
@@ -106,57 +128,62 @@
      {
        title: "综合体系-标准-层级管理",
        path: "/standard/layer",
        permissions: ["systemHierarchy:*"]
        permissions: ["systemHierarchy:*"],
      },
      {
        title: "综合体系-标准-问题管理",
        path: "/standard/problems",
        permissions: ["systemProblem:*"]
        permissions: ["systemProblem:*"],
      },
      {
        title: "综合体系-模型管理",
        path: "/standard/models",
        permissions: ["systemModel:*"]
        permissions: ["systemModel:*"],
      },
      {
        title: "综合体系-专家管理",
        path: "/standard/expert",
        permissions: ["systemExpert:*"]
        permissions: ["systemExpert:*"],
      },
      {
        title: "设备体系-标准-层级管理",
        path: "/standard/deviceLayer",
        permissions: ["deviceHierarchy:*"]
        permissions: ["deviceHierarchy:*"],
      },
      {
        title: "设备体系-标准-问题管理",
        path: "/standard/deviceProblems",
        permissions: ["deviceProblem:*"]
        permissions: ["deviceProblem:*"],
      },
      {
        title: "设备体系-模型管理",
        path: "/standard/deviceModels",
        permissions: ["deviceModel:*"]
        permissions: ["deviceModel:*"],
      },
      {
        title: "设备体系-专家管理",
        path: "/standard/deviceExperts",
        permissions: ["deviceExpert:*"]
        permissions: ["deviceExpert:*"],
      },
      {
        title: "实测实量体系-标准-层级管理",
        path: "/standard/measurementLayer",
        permissions: ["*"]
        permissions: ["*"],
      },
      {
        title: "实测实量体系-标准-规则管理",
        path: "/standard/measurementRule",
        permissions: ["*"]
        permissions: ["*"],
      },
      {
        title: "实测实量-模型管理",
        path: "/standard/measurementModel",
        permissions: ["*"]
        permissions: ["*"],
      },
      {
        title: "岗位设置",
        path: "/standard/position",
        permissions: ["*"],
      },
    ],
  },
@@ -168,7 +195,7 @@
      {
        title: "计划管理",
        path: "/procucePlan/management",
        permissions: ["plan:*"]
        permissions: ["plan:*"],
      },
      // {
      //   title: "委托任务",
@@ -185,22 +212,32 @@
      {
        title: "正确做法",
        path: "/businessData/correct-practice",
        permissions: ["warningRecord:*"]
        permissions: ["warningRecord:*"],
      },
      {
        title: "综合问题",
        path: "/system/error",
        permissions: ["errorRecord:*"]
        permissions: ["errorRecord:*"],
      },
      {
        title: "设备问题",
        path: "/device/error",
        permissions: ["deviceRecord:*"]
        permissions: ["deviceRecord:*"],
      },
      {
        title: "测量记录",
        path: "/businessData/measure-record",
        permissions: ["*"]
        permissions: ["*"],
      },
      {
        title: "在岗情况",
        path: "/businessData/on-duty",
        permissions: ["*"],
      },
      {
        title: "检查情况",
        path: "/businessData/check",
        permissions: ["*"],
      },
    ],
  },
@@ -212,7 +249,7 @@
      {
        title: "模版清单",
        path: "/report/module",
        permissions: ["reportTemplate:*"]
        permissions: ["reportTemplate:*"],
      },
    ],
  },
@@ -224,7 +261,7 @@
      {
        title: "档案管理",
        path: "/document/list",
        permissions: ["archive:*"]
        permissions: ["archive:*"],
      },
    ],
  },
@@ -236,17 +273,17 @@
      {
        title: "模糊评价",
        path: "/project/fuzzy",
        permissions: ["fuzzyEvaluation:*"]
        permissions: ["fuzzyEvaluation:*"],
      },
      {
        title: "打分评价",
        path: "/project/calc",
        permissions: ["scoreEvaluation:*"]
        permissions: ["scoreEvaluation:*"],
      },
      {
        title: "测量评价",
        path: "/project/measurement",
        permissions: ["*"]
        permissions: ["*"],
      },
    ],
  },
@@ -258,12 +295,12 @@
      {
        title: "数字地图",
        path: "/map/digital-map",
        permissions: ["*"]
        permissions: ["*"],
      },
      {
        title: "地图配置",
        path: "/map/map-config",
        permissions: ["*"]
        permissions: ["*"],
      },
    ],
  },
estate-frontend-v2024/src/config/routeMap.js
@@ -57,6 +57,12 @@
const Error404 = Loadable({ loader: () => import(/*webpackChunkName:'Error404'*/'@/views/error/404'), loading: Loading });
const Bug = Loadable({ loader: () => import(/*webpackChunkName:'Bug'*/'@/views/bug'), loading: Loading });
const Personal = Loadable({ loader: () => import(/*webpackChunkName:'Personal'*/'@/views/personal'), loading: Loading });
const AccountSetting = Loadable({ loader: () => import(/*webpackChunkName:'AccountSetting'*/'@/views/screenSetting/accountSetting'), loading: Loading });
const AccidentTypeSetting = Loadable({ loader: () => import(/*webpackChunkName:'AccidentTypeSetting'*/'@/views/screenSetting/accidentTypeSetting'), loading: Loading });
const AccidentMessageSetting = Loadable({ loader: () => import(/*webpackChunkName:'AccidentMessageSetting'*/'@/views/screenSetting/accidentMessageSetting'), loading: Loading });
const PositionSetting = Loadable({ loader: () => import(/*webpackChunkName:'PositionSetting'*/'@/views/standard/position'), loading: Loading });
const OnDuty = Loadable({ loader: () => import(/*webpackChunkName:'OnDuty'*/'@/views/business/onDuty'), loading: Loading });
const Check = Loadable({ loader: () => import(/*webpackChunkName:'Check'*/'@/views/business/check'), loading: Loading });
export default [
  { path: "/dashboard", component: Dashboard },
@@ -116,4 +122,11 @@
  { path: "/bug", component: Bug },
  { path: "/personal", component: Personal },
  { path: "/error/404", component: Error404 },
  { path: "/screenSetting/accountSetting", component: AccountSetting },
  { path: "/screenSetting/accidentTypeSetting", component: AccidentTypeSetting },
  { path: "/screenSetting/accidentMessageSetting", component: AccidentMessageSetting },
  { path: "/standard/position", component: PositionSetting },
  { path: "/businessData/on-duty", component: OnDuty },
  { path: "/businessData/check", component: Check },
];
estate-frontend-v2024/src/views/business/check.jsx
New file
@@ -0,0 +1,172 @@
import React from "react";
import { Button, Card, Divider, Select, Table, Modal } from "antd";
import { deleteDataProblem, getBusinessDataProbList } from "@/api/business";
import "../business/style/clientInfo.less";
import {
  errorLevelMap,
  errorReviewStateMap,
  riskLevelMap,
} from "../common/constants";
import CorrectPractice from "./correctPractice";
import EditDataProblemForm from "./forms/edit-dataProblem-form";
import EditDataPForm from "./forms/edit-dataP-form";
import { formatDeletedString } from "../common/common_func";
import ImagePreview from "./components/imagePreview";
import ImagePreviewView from "./components/imagePreview";
import Spacer from "../common/components/Spacer";
import { includePermission } from "../../utils/auth";
import { exportDataProblem } from "../../api/export";
const { Column } = Table;
const { Option } = Select;
const axios = require("axios");
class Check extends CorrectPractice {
  moduleName = "errorRecord";
  getEntityList(pageInfo, listBody) {
    return getBusinessDataProbList(pageInfo, listBody);
  }
  deleteEntities(ids) {
    return deleteDataProblem(ids);
  }
  async exportEntities(listBody) {
    return exportDataProblem(listBody);
  }
  handleEditAssignee = (row) => {
    this.setState({
      currentRowData: JSON.parse(JSON.stringify(row)),
      editDataPModalVisible: true,
      editDataPModalLoading: false,
    });
  };
  handleEditDataPCancel = (row) => {
    this.setState({
      editDataPModalVisible: false,
      editDataPModalLoading: false,
    });
  };
  render() {
    const { entities } = this.state;
    const title = this.getTitle();
    return (
      <div className="app-container">
        <Card title={title}>
          <Table
            bordered
            rowKey="id"
            rowSelection={{
              type: "checkbox",
              selectedRowKeys: this.state.selectedRowKeys,
              onChange: (selectedRowKeys, selectedRows) => {
                this.setState({
                  selectedEntities: selectedRows,
                  selectedRowKeys: selectedRowKeys,
                });
              },
            }}
            dataSource={entities}
            pagination={false}
            scroll={{ x: "100%" }}
          >
            <Column
              title="计划名称"
              key="planName"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>{formatDeletedString(row.planName)}</span>
              )}
            />
            <Column
              title="项目"
              key="projectName"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>{formatDeletedString(row.projectName)}</span>
              )}
            />
            <Column
              title="委托方"
              key="projectName"
              align="center"
              ellipsis={true}
            />
            <Column
              title="安全告知单"
              key="hierarchyName"
              dataIndex="hierarchyName"
              align="center"
              ellipsis={true}
            />
            <Column
              title="检查人员照片"
              key="problemPart"
              align="center"
              dataIndex="problemPart"
              ellipsis={true}
            />
            <Column
              title="廉政告知单"
              dataIndex="problem.info"
              key="problem.info"
              align="center"
              ellipsis={true}
            />
            <Column
              title="检查时间"
              key="creator.name"
              align="center"
              dataIndex="creator.name"
              ellipsis={true}
            />
            <Column
              title="操作"
              key="action"
              width={340}
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>
                  <Button
                    title="详情"
                    hidden={!includePermission(this.moduleName + ":edit")}
                    onClick={this.handleEditEntity.bind(null, row)}
                  >
                    详情
                  </Button>
                </span>
              )}
            />
          </Table>
          <br />
          {this.renderPagination()}
        </Card>
        <Modal
          title="在岗情况"
          visible={this.state.editModalVisible}
          onCancel={this.handleEditEntityCancel}
        >
          <div className="detail">
            <div>计划名称:xxx</div>
            <div>项目:xxx</div>
            <div>检查标题:xxx</div>
            <div>检查时间:xxx</div>
            <div>安全告知单:</div>
            <div>检查人员照片:</div>
            <div>廉政告知单:</div>
          </div>
        </Modal>
      </div>
    );
  }
}
export default Check;
estate-frontend-v2024/src/views/business/clientInfo.jsx
@@ -3,6 +3,8 @@
import {getClientList, deleteClient, editClient} from "@/api/business";
import {getUsersOptions} from '@/api/user'
import EditClientForm from "./forms/edit-client-form"
import EditClientParamsForm from "./forms/edit-clientParams-form"
import './style/clientInfo.less'
import {clientTypeMap} from "../common/constants";
import {toOptionsData} from "../common/common_func";
@@ -59,7 +61,7 @@
    render() {
        const {entities} = this.state
        const title = (
            <div className="title flex">
            <div className="flex title">
                <div>
                    <Input
                        style={inputLongStyle}
@@ -138,8 +140,10 @@
                        <Column title="委托方意向" dataIndex="intention" key="intention" align="center" ellipsis={true}/>
                        <Column title="创建时间" key="createTime" dataIndex="createTime" align="center" ellipsis={true}/>
                        <Column title="创建人" dataIndex="creator.name" key="creator.name" align="center" ellipsis={true}/>
                        <Column title="操作" key="action" width={200} align="center" render={(text, row) => (
                        <Column title="操作" key="action" width={300} align="center" render={(text, row) => (
                            <span>
                                {this.renderParameterSettingButton(row, 'client:edit')}
                                <Spacer/>
                                {this.renderEditButton(row, 'client:edit')}
                                <Spacer/>
                                {this.renderDeleteButton(row, 'client:delete')}
@@ -157,6 +161,14 @@
                    onCancel={this.handleEditEntityCancel}
                    onOk={this.handleEditEntityOk}
                />
                <EditClientParamsForm
                    currentRowData={this.state.currentRowData}
                    wrappedComponentRef={formRef => this.editParamsFormRef = formRef}
                    visible={this.state.parameterSettingModalVisible}
                    confirmLoading={this.state.parameterSettingModalLoading}
                    onCancel={this.handleParameterSettingEntityCancel}
                    onOk={this.handleParameterSettingEntityOk}
                />
            </div>
        );
    }
estate-frontend-v2024/src/views/business/dataProblem.jsx
@@ -1,102 +1,217 @@
import React from "react";
import {Button, Card, Divider, Select, Table} from "antd";
import {deleteDataProblem, getBusinessDataProbList} from "@/api/business";
import '../business/style/clientInfo.less'
import {errorLevelMap, errorReviewStateMap, riskLevelMap} from "../common/constants";
import { Button, Card, Divider, Select, Table } from "antd";
import { deleteDataProblem, getBusinessDataProbList } from "@/api/business";
import "../business/style/clientInfo.less";
import {
  errorLevelMap,
  errorReviewStateMap,
  riskLevelMap,
} from "../common/constants";
import CorrectPractice from "./correctPractice";
import EditDataProblemForm from "./forms/edit-dataProblem-form";
import {formatDeletedString} from "../common/common_func";
import EditDataPForm from "./forms/edit-dataP-form";
import { formatDeletedString } from "../common/common_func";
import ImagePreview from "./components/imagePreview";
import ImagePreviewView from "./components/imagePreview";
import Spacer from "../common/components/Spacer";
import {includePermission} from "../../utils/auth";
import {exportDataProblem} from "../../api/export";
import { includePermission } from "../../utils/auth";
import { exportDataProblem } from "../../api/export";
const {Column} = Table;
const {Option} = Select
const axios = require('axios');
const { Column } = Table;
const { Option } = Select;
const axios = require("axios");
class DataProb extends CorrectPractice {
  moduleName = "errorRecord";
    moduleName = 'errorRecord'
  getEntityList(pageInfo, listBody) {
    return getBusinessDataProbList(pageInfo, listBody);
  }
    getEntityList(pageInfo, listBody) {
        return getBusinessDataProbList(pageInfo, listBody)
    }
  deleteEntities(ids) {
    return deleteDataProblem(ids);
  }
    deleteEntities(ids) {
        return deleteDataProblem(ids)
    }
  async exportEntities(listBody) {
    return exportDataProblem(listBody);
  }
    async exportEntities(listBody) {
        return exportDataProblem(listBody)
    }
  handleEditAssignee = (row) => {
    this.setState({
      currentRowData: JSON.parse(JSON.stringify(row)),
      editDataPModalVisible: true,
      editDataPModalLoading: false,
    });
  };
    render() {
        const {entities} = this.state
        const title = this.getTitle()
        return (
            <div className="app-container">
                <Card title={title}>
                    <Table
                        bordered
                        rowKey="id"
                        rowSelection={{
                            type: 'checkbox',
                            selectedRowKeys: this.state.selectedRowKeys,
                            onChange: (selectedRowKeys, selectedRows) => {
                                this.setState({
                                    selectedEntities: selectedRows,
                                    selectedRowKeys: selectedRowKeys
                                })
                            },
                        }}
                        dataSource={entities}
                        pagination={false}
                        scroll={{x: '100%'}}>
                        <Column title="序号" dataIndex="id" key="id" align="center" ellipsis={true}/>
                        <Column title="计划" key="planName" align="center" ellipsis={true} render={(text, row) => (
                            <span>{formatDeletedString(row.planName)}</span>
                        )}/>
                        <Column title="项目" key="projectName" align="center" ellipsis={true} render={(text, row) => (
                            <span>{formatDeletedString(row.projectName)}</span>
                        )}/>
                        <Column title="检查内容" key="hierarchyName" dataIndex="hierarchyName" align="center" ellipsis={true}/>
                        <Column title="问题部位" key="problemPart" align="center" dataIndex="problemPart" ellipsis={true}/>
                        <Column title="问题描述" dataIndex="problem.info" key="problem.info" align="center" ellipsis={true}/>
                        <Column title="问题备注" dataIndex="remark" key="remark" align="center" ellipsis={true}/>
                        <Column title="隐患等级" dataIndex="level" key="level" ellipsis={true} render={(text, row) => (
                            <span>{errorLevelMap[row.level]}</span>
                        )}/>
                        <Column title="复查状态" key="errorReviewState" align="center" ellipsis={true} render={(text, row) => (
                            <span>{row.errorReviewState ? errorReviewStateMap[row.errorReviewState] : '未复查'}</span>
                        )}/>
                        {this.renderImagePreviewColumn()}
                        <Column title="创建人" key="creator.name" align="center" dataIndex="creator.name" ellipsis={true}/>
                        <Column title="操作" key="action" width={255} align="center" ellipsis={true}
                                render={(text, row) => (
                                    <span>
                                    <Button title="详情" hidden={!includePermission(this.moduleName + ":edit")}
                                            onClick={this.handleEditEntity.bind(null, row)}>详情</Button>
                                    <Spacer/>
                                    {this.renderDeleteButton(row, this.moduleName + ":delete")}
                                    </span>
                                )}/>
                    </Table>
                    <br/>
                    {this.renderPagination()}
                </Card>
                <EditDataProblemForm
                    currentRowData={this.state.currentRowData}
                    wrappedComponentRef={formRef => this.editFormRef = formRef}
                    visible={this.state.editModalVisible}
                    confirmLoading={this.state.editModalLoading}
                    onCancel={this.handleEditEntityCancel}
                />
                {this.renderImagePreviewModal()}
            </div>
        );
    }
  handleEditDataPCancel = (row) => {
    this.setState({
      editDataPModalVisible: false,
      editDataPModalLoading: false,
    });
  };
  render() {
    const { entities } = this.state;
    const title = this.getTitle();
    return (
      <div className="app-container">
        <Card title={title}>
          <Table
            bordered
            rowKey="id"
            rowSelection={{
              type: "checkbox",
              selectedRowKeys: this.state.selectedRowKeys,
              onChange: (selectedRowKeys, selectedRows) => {
                this.setState({
                  selectedEntities: selectedRows,
                  selectedRowKeys: selectedRowKeys,
                });
              },
            }}
            dataSource={entities}
            pagination={false}
            scroll={{ x: "100%" }}
          >
            <Column
              title="序号"
              dataIndex="id"
              key="id"
              align="center"
              ellipsis={true}
            />
            <Column
              title="计划"
              key="planName"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>{formatDeletedString(row.planName)}</span>
              )}
            />
            <Column
              title="项目"
              key="projectName"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>{formatDeletedString(row.projectName)}</span>
              )}
            />
            <Column
              title="检查内容"
              key="hierarchyName"
              dataIndex="hierarchyName"
              align="center"
              ellipsis={true}
            />
            <Column
              title="问题部位"
              key="problemPart"
              align="center"
              dataIndex="problemPart"
              ellipsis={true}
            />
            <Column
              title="问题描述"
              dataIndex="problem.info"
              key="problem.info"
              align="center"
              ellipsis={true}
            />
            <Column
              title="问题备注"
              dataIndex="remark"
              key="remark"
              align="center"
              ellipsis={true}
            />
            <Column
              title="隐患等级"
              dataIndex="level"
              key="level"
              ellipsis={true}
              render={(text, row) => <span>{errorLevelMap[row.level]}</span>}
            />
            <Column
              title="复查状态"
              key="errorReviewState"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>
                  {row.errorReviewState
                    ? errorReviewStateMap[row.errorReviewState]
                    : "未复查"}
                </span>
              )}
            />
            <Column
              title="责任人"
              key="assignee.name"
              align="center"
              ellipsis={true}
            />
            {this.renderImagePreviewColumn()}
            <Column
              title="创建人"
              key="creator.name"
              align="center"
              dataIndex="creator.name"
              ellipsis={true}
            />
            <Column
              title="操作"
              key="action"
              width={340}
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>
                  <Button
                    title="编辑责任人"
                    hidden={!includePermission(this.moduleName + ":edit")}
                    onClick={this.handleEditAssignee.bind(null, row)}
                  >
                    编辑责任人
                  </Button>
                  <Spacer />
                  <Button
                    title="详情"
                    hidden={!includePermission(this.moduleName + ":edit")}
                    onClick={this.handleEditEntity.bind(null, row)}
                  >
                    详情
                  </Button>
                  <Spacer />
                  {this.renderDeleteButton(row, this.moduleName + ":delete")}
                </span>
              )}
            />
          </Table>
          <br />
          {this.renderPagination()}
        </Card>
        <EditDataProblemForm
          currentRowData={this.state.currentRowData}
          wrappedComponentRef={(formRef) => (this.editFormRef = formRef)}
          visible={this.state.editModalVisible}
          confirmLoading={this.state.editModalLoading}
          onCancel={this.handleEditEntityCancel}
        />
        {this.renderImagePreviewModal()}
        <EditDataPForm
          currentRowData={this.state.currentRowData}
          wrappedComponentRef={(formRef) => (this.editFormRef = formRef)}
          visible={this.state.editDataPModalVisible}
          confirmLoading={this.state.editDataPModalLoading}
          onCancel={this.handleEditDataPCancel}
        />
      </div>
    );
  }
}
export default DataProb;
estate-frontend-v2024/src/views/business/forms/edit-clientParams-form.jsx
New file
@@ -0,0 +1,666 @@
import React from "react";
import {
  Form,
  Input,
  Select,
  Modal,
  Tabs,
  Table,
  Checkbox,
  Upload,
  Icon,
  Row,
  Col,
  Switch,
  Radio,
  Button,
} from "antd";
import BaseForm from "../../common/edit-form-base";
import "../style/clientParams.less";
import { checkFileSize } from "../../common/common_func";
const { Option } = Select;
const { TabPane } = Tabs;
const { Column } = Table;
function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
}
// 初始表格数据
const initialDataSource = [
  { id: 1, title: "端口", subTitle: "大屏板块", visible: true },
  { id: 2, title: "委托方端", subTitle: "项目总数(在建工程)", visible: true },
  {
    id: 3,
    title: "委托方端",
    subTitle: "大型机械设备数(在建工程)",
    visible: true,
  },
  {
    id: 4,
    title: "委托方端",
    subTitle: "重大隐患数(在建工程)",
    visible: true,
  },
  { id: 5, title: "委托方端", subTitle: "项目总数(固定资产)", visible: true },
  {
    id: 6,
    title: "委托方端",
    subTitle: "重大隐患数(固定资产)",
    visible: true,
  },
  { id: 7, title: "委托方端", subTitle: "事故简讯", visible: true },
  { id: 8, title: "委托方端", subTitle: "工作展示", visible: true },
  { id: 9, title: "项目端", subTitle: "各分项隐患趋势", visible: true },
  { id: 10, title: "项目端", subTitle: "隐患数量", visible: true },
  { id: 11, title: "项目端", subTitle: "设备数量", visible: true },
  { id: 12, title: "项目端", subTitle: "查看报告入口", visible: true },
  { id: 13, title: "项目端", subTitle: "人员在岗率", visible: true },
  { id: 14, title: "项目端", subTitle: "重大风险源", visible: true },
  { id: 15, title: "项目端", subTitle: "项目风险趋势", visible: true },
];
class EditClientParamsForm extends BaseForm {
  constructor(props) {
    super(props);
    this.state = {
      editableData: this.initEditableData(),
      dataSource: initialDataSource,
      previewVisible: false,
      previewImage: "",
      assetRules: {
        A: [[{ level: undefined, count: undefined }]],
        B: [[{ level: undefined, count: undefined }]],
        C: [[{ level: undefined, count: undefined }]],
      },
    };
  }
  initEditableData() {
    return {
      name: "",
      file: [],
    };
  }
  handleCancel = () =>
    this.setState({
      previewVisible: false,
      previewImage: "",
    });
  handlePreview = async (file) => {
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj);
    }
    this.setState({
      previewVisible: true,
      previewImage: file.url || file.preview,
    });
  };
  // 切换可见状态
  handleCheckboxChange = (record) => {
    this.setState((prevState) => ({
      dataSource: prevState.dataSource.map((item) =>
        item.id === record.id ? { ...item, visible: !item.visible } : item,
      ),
    }));
  };
  // 添加 OR 条件
  addOrCondition = (type) => {
    this.setState((prev) => ({
      assetRules: {
        ...prev.assetRules,
        [type]: [
          ...prev.assetRules[type],
          [{ level: undefined, count: undefined }],
        ],
      },
    }));
  };
  // 删除 OR 条件
  removeOrCondition = (type, orIndex) => {
    this.setState((prev) => {
      const rules = prev.assetRules[type].filter(
        (_, index) => index !== orIndex,
      );
      return {
        assetRules: {
          ...prev.assetRules,
          [type]: rules.length
            ? rules
            : [[{ level: undefined, count: undefined }]], // 至少保留一组
        },
      };
    });
  };
  // 删除 AND 条件
  removeAndCondition = (type, orIndex, andIndex) => {
    this.setState((prev) => {
      const rules = [...prev.assetRules[type]];
      // 删除 AND
      rules[orIndex] = rules[orIndex].filter((_, index) => index !== andIndex);
      // 如果 OR 里已经没有 AND 了,删除整个 OR
      if (rules[orIndex].length === 0) {
        rules.splice(orIndex, 1);
      }
      return {
        assetRules: {
          ...prev.assetRules,
          [type]: rules,
        },
      };
    });
  };
  // 添加 AND 条件
  addAndCondition = (type, orIndex) => {
    this.setState((prev) => {
      const rules = [...prev.assetRules[type]];
      rules[orIndex] = [
        ...rules[orIndex],
        { level: undefined, count: undefined },
      ];
      return { assetRules: { ...prev.assetRules, [type]: rules } };
    });
  };
  updateCondition = (type, orIndex, andIndex, key, value) => {
    this.setState((prev) => {
      const rules = [...prev.assetRules[type]];
      rules[orIndex][andIndex][key] = value;
      return { assetRules: { ...prev.assetRules, [type]: rules } };
    });
  };
  render() {
    const { visible, onCancel, onOk, form, confirmLoading } = this.props;
    const { getFieldDecorator } = form;
    const { name, file } = this.state.editableData;
    const { dataSource, previewVisible, previewImage, assetRules } = this.state;
    const uploadButton = (
      <div>
        <Icon type="plus" />
      </div>
    );
    return (
      <Modal
        title="参数设置"
        visible={visible}
        onCancel={onCancel}
        onOk={() => onOk(dataSource)}
        width={1100}
        destroyOnClose
        confirmLoading={confirmLoading}
      >
        <Tabs defaultActiveKey="1">
          {/* 参数设置 */}
          <TabPane tab="参数设置" key="1">
            <Form layout="inline">
              <Row gutter={24}>
                <Col span={12}>
                  <Form.Item label="大屏显示名称">
                    {getFieldDecorator("name", {
                      rules: [
                        { required: true, message: "请输入大屏显示名称!" },
                      ],
                      initialValue: name,
                      onChange: this.handleFieldChange("name"),
                    })(
                      <Input
                        style={{ width: "300px" }}
                        maxLength={15}
                        placeholder="请输入15字内"
                      />,
                    )}
                  </Form.Item>
                </Col>
                <Col span={12}>
                  <Form.Item label="LOGO">
                    {getFieldDecorator("file", {
                      valuePropName: "file",
                      // getValueFromEvent: singleFile,
                      initialValue: file,
                      rules: [{ required: true, message: "请上传LOGO" }],
                    })(
                      <div>
                        <Upload
                          disabled={this.uploading}
                          name={"file"}
                          maxCount={1}
                          listType="picture-card"
                          multiple={false}
                          customRequest={this.uploadAttachment.bind(
                            null,
                            "file",
                          )}
                          onRemove={() => {
                            this.setFieldValue("file", []);
                          }}
                          onPreview={this.handlePreview}
                          beforeUpload={checkFileSize}
                          accept="image/*"
                        >
                          {!file || file.length === 0 ? uploadButton : null}
                        </Upload>
                        <Modal
                          visible={previewVisible}
                          footer={null}
                          onCancel={this.handleCancel}
                        >
                          <img
                            alt="example"
                            style={{ width: "100%" }}
                            src={previewImage}
                          />
                        </Modal>
                      </div>,
                    )}
                  </Form.Item>
                </Col>
                <Col span={24}>
                  <Form.Item label="是否显示整改状态">
                    {getFieldDecorator("name", {
                      rules: [
                        { required: true, message: "请选择是否显示整改状态!" },
                      ],
                      initialValue: name,
                      onChange: this.handleFieldChange("name"),
                    })(
                      <div>
                        <span>
                          重大隐患:
                          <Switch />
                        </span>
                        <span style={{ marginLeft: 20 }}>
                          一般(设备/安全)隐患:
                          <Switch />
                        </span>
                        <div
                          style={{
                            fontSize: "12px",
                            color: "#999",
                            lineHeight: "12px",
                          }}
                        >
                          委托方查看整改列表时,是否显示整改状态字段
                        </div>
                      </div>,
                    )}
                  </Form.Item>
                </Col>
                <Col span={24} style={{ marginTop: 16 }}>
                  <Form.Item label="报告评价设置">
                    {getFieldDecorator("name", {
                      rules: [
                        { required: true, message: "请选择报告评价设置!" },
                      ],
                      initialValue: name,
                      onChange: this.handleFieldChange("name"),
                    })(
                      <div>
                        <Radio.Group>
                          <Radio value={1}>模糊评价</Radio>
                          <Radio value={2}>打分评价</Radio>
                        </Radio.Group>
                        <div
                          style={{
                            fontSize: "12px",
                            color: "#999",
                            lineHeight: "12px",
                          }}
                        >
                          委托方查看项目报告时,报告记录显示模糊评价还是打分评价数据
                        </div>
                      </div>,
                    )}
                  </Form.Item>
                </Col>
                <Col span={24} style={{ marginTop: 16 }}>
                  <Form.Item label="报告生成方式">
                    {getFieldDecorator("name", {
                      rules: [
                        { required: true, message: "请选择报告生成方式!" },
                      ],
                      initialValue: name,
                      onChange: this.handleFieldChange("name"),
                    })(
                      <div>
                        <div>
                          安全报告
                          <Select style={{ width: 200, marginLeft: 20 }}>
                            <Option value={1}>默认模板</Option>
                          </Select>
                        </div>
                        <div>
                          设备报表
                          <Select style={{ width: 200, marginLeft: 20 }}>
                            <Option value={1}>默认模板</Option>
                          </Select>
                        </div>
                        <div
                          style={{
                            fontSize: "12px",
                            color: "#999",
                            lineHeight: "12px",
                          }}
                        >
                          委托方查看项目报告时,报告样式是用哪个模板
                        </div>
                      </div>,
                    )}
                  </Form.Item>
                </Col>
                <Col span={24} style={{ marginTop: 16 }}>
                  <Form.Item label="委托方项目总数">
                    {getFieldDecorator("name", {
                      rules: [
                        { required: true, message: "请输入委托方项目总数!" },
                      ],
                      initialValue: name,
                      onChange: this.handleFieldChange("name"),
                    })(
                      <Input
                        style={{ width: "300px" }}
                        type="number"
                        placeholder="请输入项目数"
                      />,
                    )}
                  </Form.Item>
                </Col>
                <Col span={24} style={{ marginTop: 16 }}>
                  <Form.Item label="风险等级参数设置">
                    {getFieldDecorator("name", {
                      rules: [
                        { required: true, message: "请设置风险等级参数!" },
                      ],
                      initialValue: name,
                      onChange: this.handleFieldChange("name"),
                    })(
                      <div className="container">
                        <div>在建项目:</div>
                        <div className="item">
                          <div className="label">A类:</div>
                          <div className="value">
                            平均分大于等于
                            <Input
                              className="value-input"
                              type="number"
                              placeholder="请输入分数"
                            />
                          </div>
                        </div>
                        <div className="item">
                          <div className="label">B类:</div>
                          <div className="value">
                            平均分大于等于
                            <Input
                              className="value-input"
                              type="number"
                              placeholder="请输入分数"
                            />
                          </div>
                        </div>
                        <div className="item">
                          <div className="label">C类:</div>
                          <div className="value">
                            平均分大于等于
                            <Input
                              className="value-input"
                              type="number"
                              placeholder="请输入分数"
                            />
                          </div>
                        </div>
                        <div className="item">
                          <div className="label">分数占比:</div>
                          <div className="footerValue">
                            <div>
                              安全检查
                              <Input
                                className="value-input"
                                type="number"
                                placeholder="请输入占比"
                              />{" "}
                              %
                            </div>
                            <div>
                              设备检查
                              <Input
                                className="value-input"
                                type="number"
                                placeholder="请输入占比"
                              />{" "}
                              %
                            </div>
                          </div>
                        </div>
                        <div>资产项目:</div>
                        {["A", "B", "C"].map((type) => (
                          <div
                            className="flex"
                            key={type}
                            style={{ marginTop: 12 }}
                          >
                            <div className="label">{type}类:</div>
                            <div>
                              <Button
                                type="primary"
                                onClick={() => this.addOrCondition(type)}
                              >
                                添加OR条件
                              </Button>
                              {assetRules[type].map((orGroup, orIndex) => (
                                <div
                                  key={orIndex}
                                  style={{
                                    alignItems: "center",
                                    flexWrap: "wrap",
                                    width: 700,
                                  }}
                                  className="flex"
                                >
                                  {orIndex > 0 && (
                                    <div>
                                      <span
                                        style={{
                                          color: "#ff4d4f",
                                        }}
                                      >
                                        OR
                                      </span>
                                      <Icon
                                        type="delete"
                                        style={{
                                          marginLeft: 8,
                                          fontSize: 18,
                                          color: "#FF4D4F",
                                          cursor: "pointer",
                                          marginRight: 8,
                                        }}
                                        onClick={() =>
                                          this.removeOrCondition(type, orIndex)
                                        }
                                      />
                                    </div>
                                  )}
                                  {orGroup.map((andItem, andIndex) => (
                                    <div
                                      key={andIndex}
                                      style={{
                                        display: "flex",
                                        alignItems: "center",
                                      }}
                                    >
                                      {andIndex > 0 && (
                                        <div>
                                          <span
                                            style={{
                                              marginLeft: 8,
                                              color: "#999",
                                            }}
                                          >
                                            and
                                          </span>
                                          <Icon
                                            type="minus-circle"
                                            theme="filled"
                                            style={{
                                              marginLeft: 8,
                                              fontSize: 18,
                                              color: "#FF4D4F",
                                              cursor: "pointer",
                                              marginRight: 8,
                                            }}
                                            onClick={() =>
                                              this.removeAndCondition(
                                                type,
                                                orIndex,
                                                andIndex,
                                              )
                                            }
                                          />
                                        </div>
                                      )}
                                      <Select
                                        style={{ width: 120 }}
                                        placeholder="隐患级别"
                                        value={andItem.level}
                                        onChange={(val) =>
                                          this.updateCondition(
                                            type,
                                            orIndex,
                                            andIndex,
                                            "level",
                                            val,
                                          )
                                        }
                                      >
                                        <Option value={1}>一级隐患</Option>
                                        <Option value={2}>二级隐患</Option>
                                        <Option value={3}>三级隐患</Option>
                                        <Option value={4}>四级隐患</Option>
                                      </Select>
                                      <Input
                                        style={{ width: 120, marginLeft: 16 }}
                                        type="number"
                                        placeholder="请输入数量"
                                        value={andItem.count}
                                        onChange={(e) =>
                                          this.updateCondition(
                                            type,
                                            orIndex,
                                            andIndex,
                                            "count",
                                            e.target.value,
                                          )
                                        }
                                      />
                                    </div>
                                  ))}
                                  <Icon
                                    type="plus-circle"
                                    theme="filled"
                                    style={{
                                      marginLeft: 8,
                                      fontSize: 18,
                                      color: "#1DA57A",
                                      cursor: "pointer",
                                    }}
                                    onClick={() =>
                                      this.addAndCondition(type, orIndex)
                                    }
                                  />
                                </div>
                              ))}
                            </div>
                          </div>
                        ))}
                      </div>,
                    )}
                  </Form.Item>
                </Col>
              </Row>
            </Form>
          </TabPane>
          {/* 权限板块设置 */}
          <TabPane tab="权限板块设置" key="2">
            <Table
              rowKey="id"
              dataSource={dataSource}
              bordered
              pagination={false}
            >
              <Column
                title="一级权限模块"
                dataIndex="title"
                key="title"
                render={(text, row, index) => {
                  if (index === 0) {
                    return { children: text, props: { rowSpan: 1 } };
                  }
                  if (index === 1) {
                    return { children: "委托方端", props: { rowSpan: 7 } };
                  }
                  if (index > 1 && index <= 7) {
                    return { children: null, props: { rowSpan: 0 } };
                  }
                  if (index === 8) {
                    return { children: "项目端", props: { rowSpan: 7 } };
                  }
                  if (index > 8 && index <= 14) {
                    return { children: null, props: { rowSpan: 0 } };
                  }
                  return text;
                }}
              />
              <Column
                title="二级权限模块"
                dataIndex="subTitle"
                key="subTitle"
              />
              <Column
                title="是否可见"
                key="visible"
                render={(text, row) => (
                  <Checkbox
                    checked={row.visible}
                    onChange={() => this.handleCheckboxChange(row)}
                  />
                )}
              />
            </Table>
          </TabPane>
        </Tabs>
      </Modal>
    );
  }
}
export default Form.create({ name: "EditClientParamsForm" })(
  EditClientParamsForm,
);
estate-frontend-v2024/src/views/business/forms/edit-dataP-form.jsx
New file
@@ -0,0 +1,45 @@
import React from "react";
import { Form, Input, Modal } from "antd";
import BaseForm from "../../common/edit-form-base";
class EditClientForm extends BaseForm {
  initEditableData() {
    return {
      name: "",
    };
  }
  render() {
    const { visible, onCancel, onOk, form, confirmLoading } = this.props;
    const { getFieldDecorator } = form;
    const { name } = this.state.editableData;
    // 替换标题为"编辑责任人"
    return (
      <Modal
        title="编辑责任人"
        visible={visible}
        onCancel={onCancel}
        onOk={onOk}
        destroyOnClose
        confirmLoading={confirmLoading}
      >
        <Form {...this.formItemLayout}>
          <Form.Item label="责任人:">
            {getFieldDecorator("name", {
              rules: [{ required: true, message: "请输入责任人!" }],
              initialValue: name,
              onChange: this.handleFieldChange("name"),
            })(
              <Input
                style={{ marginLeft: "10px" }}
                placeholder="请输入责任人"
              />,
            )}
          </Form.Item>
        </Form>
      </Modal>
    );
  }
}
export default Form.create({ name: "EditClientForm" })(EditClientForm);
estate-frontend-v2024/src/views/business/forms/edit-project-form.jsx
@@ -224,6 +224,17 @@
                    )}
                </Form.Item>
            </div>
            <div className="p-10">
                <Form.Item label="项目规格:">
                    {getFieldDecorator("clientId", {
                        initialValue: client? {key: client.id, label: client.name} : undefined,
                        rules: [{required: true, message: '请选择委托方!'}],
                        onChange: this.handleEntitySelectChange('client')
                    })(
                    <Input placeholder="请输入项目规格" />
                    )}
                </Form.Item>
            </div>
          </div>
          <div className="grid grid-1-1-1">
            <div className="p-10">
@@ -386,11 +397,21 @@
                <Form.Item label="详细地址:">
                    {getFieldDecorator("address", {
                        initialValue: addressInfo && addressInfo.detail ? addressInfo.detail : '',
                        rules: [{required: true, message: '请输入详细地址!'}],
                        onChange: this.handleEntityFieldSelectChange('addressInfo', 'detail')
                        })(<Input placeholder="详细地址" />)}
                </Form.Item>
            </div>
            <div className="p-10">
                <Form.Item label="经纬度:">
                    {getFieldDecorator("address", {
                        initialValue: addressInfo && addressInfo.detail ? addressInfo.detail : '',
                        rules: [{required: true, message: '请输入经纬度!'}],
                        onChange: this.handleEntityFieldSelectChange('addressInfo', 'detail')
                        })(<Input placeholder="经纬度" />)}
                </Form.Item>
            </div>
            <div className="p-10">
                <Form.Item label="工程造价:" >
                    {getFieldDecorator("projectCost", {
                        initialValue: projectCost,
estate-frontend-v2024/src/views/business/forms/edit-projectPermission-form.jsx
New file
@@ -0,0 +1,124 @@
import React from "react";
import {
  Form,
  Input,
  Select,
  Modal,
  Tabs,
  Table,
  Checkbox,
  Upload,
  Icon,
  Row,
  Col,
  Switch,
  Radio,
  Button,
} from "antd";
import BaseForm from "../../common/edit-form-base";
import "../style/clientParams.less";
import { checkFileSize } from "../../common/common_func";
const { Option } = Select;
const { TabPane } = Tabs;
const { Column } = Table;
function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
}
// 初始表格数据
const initialDataSource = [
  { id: 1, title: "端口", subTitle: "大屏板块", visible: true },
  { id: 2, title: "项目端", subTitle: "各分项隐患趋势", visible: true },
  { id: 3, title: "项目端", subTitle: "隐患数量", visible: true },
  { id: 4, title: "项目端", subTitle: "设备数量", visible: true },
  { id: 5, title: "项目端", subTitle: "查看报告入口", visible: true },
  { id: 6, title: "项目端", subTitle: "人员在岗率", visible: true },
  { id: 7, title: "项目端", subTitle: "重大风险源", visible: true },
  { id: 8, title: "项目端", subTitle: "项目风险趋势", visible: true },
];
class EditClientParamsForm extends BaseForm {
  constructor(props) {
    super(props);
    this.state = {
      editableData: this.initEditableData(),
      dataSource: initialDataSource,
    };
  }
  initEditableData() {
    return {
      name: "",
    };
  }
  // 切换可见状态
  handleCheckboxChange = (record) => {
    this.setState((prevState) => ({
      dataSource: prevState.dataSource.map((item) =>
        item.id === record.id ? { ...item, visible: !item.visible } : item,
      ),
    }));
  };
  render() {
    const { visible, onCancel, onOk, form, confirmLoading } = this.props;
    const { dataSource } = this.state;
    return (
      <Modal
        title="参数设置"
        visible={visible}
        onCancel={onCancel}
        onOk={() => onOk(dataSource)}
        width={1100}
        destroyOnClose
        confirmLoading={confirmLoading}
      >
        <Table rowKey="id" dataSource={dataSource} bordered pagination={false}>
          <Column
            title="一级权限模块"
            dataIndex="title"
            key="title"
            render={(text, row, index) => {
              if (index === 0) {
                return { children: text, props: { rowSpan: 1 } };
              }
              if (index === 2) {
                return { children: "项目端", props: { rowSpan: 7 } };
              }
              if (index > 2 && index <= 8) {
                return { children: null, props: { rowSpan: 0 } };
              }
              return text;
            }}
          />
          <Column title="二级权限模块" dataIndex="subTitle" key="subTitle" />
          <Column
            title="是否可见"
            key="visible"
            render={(text, row) => (
              <Checkbox
                checked={row.visible}
                onChange={() => this.handleCheckboxChange(row)}
              />
            )}
          />
        </Table>
      </Modal>
    );
  }
}
export default Form.create({ name: "EditClientParamsForm" })(
  EditClientParamsForm,
);
estate-frontend-v2024/src/views/business/forms/edit-projectStatus-form.jsx
New file
@@ -0,0 +1,54 @@
import React from "react";
import { Form, DatePicker, Modal, Radio } from "antd";
import {clientTypeMap} from "../../common/constants";
import BaseForm from "../../common/edit-form-base";
class EditClientForm extends BaseForm {
  initEditableData () {
    return {
      date: '',
      status: 1
    }
  }
  render() {
    const { visible, onCancel, onOk, form, confirmLoading } = this.props;
    const { getFieldDecorator } = form;
    const { date, status } = this.state.editableData;
    return (
        <Modal
            title="修改状态"
            visible={visible}
            onCancel={onCancel}
            onOk={onOk}
            destroyOnClose
            confirmLoading={confirmLoading}
        >
          <Form {...this.formItemLayout}>
            <Form.Item label="">
              {getFieldDecorator("status", {
                rules: [{ required: true, message: "请选择状态!" }],
                initialValue: status,
                onChange: this.handleFieldChange('status')
              })(<Radio.Group style={{marginLeft: '10px'}}>
                <Radio value={1}>在建</Radio>
                <Radio value={2}>完成</Radio>
              </Radio.Group>)}
            </Form.Item>
            {status === 2 && <Form.Item label="完成时间:">
              {getFieldDecorator("date", {
                rules: [{ required: true, message: "请选择完成时间!" }],
                initialValue: date,
                onChange: this.handleFieldChange('date')
              })(<DatePicker style={{marginLeft: '10px'}} placeholder="请选择完成时间" />)}
            </Form.Item>}
          </Form>
        </Modal>
    );
  }
}
export default Form.create({ name: "EditClientForm" })(EditClientForm);
estate-frontend-v2024/src/views/business/onDuty.jsx
New file
@@ -0,0 +1,180 @@
import React from "react";
import { Button, Card, Divider, Select, Table, Modal } from "antd";
import { deleteDataProblem, getBusinessDataProbList } from "@/api/business";
import "../business/style/clientInfo.less";
import {
  errorLevelMap,
  errorReviewStateMap,
  riskLevelMap,
} from "../common/constants";
import CorrectPractice from "./correctPractice";
import EditDataProblemForm from "./forms/edit-dataProblem-form";
import EditDataPForm from "./forms/edit-dataP-form";
import { formatDeletedString } from "../common/common_func";
import ImagePreview from "./components/imagePreview";
import ImagePreviewView from "./components/imagePreview";
import Spacer from "../common/components/Spacer";
import { includePermission } from "../../utils/auth";
import { exportDataProblem } from "../../api/export";
const { Column } = Table;
const { Option } = Select;
const axios = require("axios");
class OnDuty extends CorrectPractice {
  moduleName = "errorRecord";
  getEntityList(pageInfo, listBody) {
    return getBusinessDataProbList(pageInfo, listBody);
  }
  deleteEntities(ids) {
    return deleteDataProblem(ids);
  }
  async exportEntities(listBody) {
    return exportDataProblem(listBody);
  }
  handleEditAssignee = (row) => {
    this.setState({
      currentRowData: JSON.parse(JSON.stringify(row)),
      editDataPModalVisible: true,
      editDataPModalLoading: false,
    });
  };
  handleEditDataPCancel = (row) => {
    this.setState({
      editDataPModalVisible: false,
      editDataPModalLoading: false,
    });
  };
  render() {
    const { entities } = this.state;
    const title = this.getTitle();
    return (
      <div className="app-container">
        <Card title={title}>
          <Table
            bordered
            rowKey="id"
            rowSelection={{
              type: "checkbox",
              selectedRowKeys: this.state.selectedRowKeys,
              onChange: (selectedRowKeys, selectedRows) => {
                this.setState({
                  selectedEntities: selectedRows,
                  selectedRowKeys: selectedRowKeys,
                });
              },
            }}
            dataSource={entities}
            pagination={false}
            scroll={{ x: "100%" }}
          >
            <Column
              title="计划名称"
              key="planName"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>{formatDeletedString(row.planName)}</span>
              )}
            />
            <Column
              title="项目"
              key="projectName"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>{formatDeletedString(row.projectName)}</span>
              )}
            />
            <Column
              title="检查内容"
              key="projectName"
              align="center"
              ellipsis={true}
            />
            <Column
              title="岗位"
              key="hierarchyName"
              dataIndex="hierarchyName"
              align="center"
              ellipsis={true}
            />
            <Column
              title="问题备注"
              key="problemPart"
              align="center"
              dataIndex="problemPart"
              ellipsis={true}
            />
            <Column
              title="图片"
              dataIndex="problem.info"
              key="problem.info"
              align="center"
              ellipsis={true}
            />
            <Column
              title="检查时间"
              key="creator.name"
              align="center"
              dataIndex="creator.name"
              ellipsis={true}
            />
            <Column
              title="在岗情况"
              key="creator.name"
              align="center"
              dataIndex="creator.name"
              ellipsis={true}
            />
            <Column
              title="操作"
              key="action"
              width={160}
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>
                  <Button
                    title="详情"
                    hidden={!includePermission(this.moduleName + ":edit")}
                    onClick={this.handleEditEntity.bind(null, row)}
                  >
                    详情
                  </Button>
                </span>
              )}
            />
          </Table>
          <br />
          {this.renderPagination()}
        </Card>
        <Modal
          title="在岗情况"
          visible={this.state.editModalVisible}
          onCancel={this.handleEditEntityCancel}
        >
            <div className="detail">
                <div>计划名称:xxx</div>
                <div>项目:xxx</div>
                <div>检查内容:xxx</div>
                <div>岗位:xxx</div>
                <div>问题备注:</div>
                <div>在岗情况:</div>
                <div>检查时间:</div>
                <div>图片:</div>
            </div>
        </Modal>
      </div>
    );
  }
}
export default OnDuty;
estate-frontend-v2024/src/views/business/projects.jsx
@@ -1,10 +1,13 @@
import React from "react";
import { Button, Card, Icon, Input, Select, Table } from "antd";
import { deleteProject, editProject, getProjectList } from "@/api/projects"
import { deleteProject, editProject, getProjectList } from "@/api/projects";
import ProjectInfo from "./components/projectInfo";
import EditProjectForm from "./forms/edit-project-form";
import './style/projects.less'
import './style/clientInfo.less'
import EditProjectPermissionForm from "./forms/edit-projectPermission-form";
import EditProjectStatusForm from "./forms/edit-projectStatus-form";
import "./style/projects.less";
import "./style/clientInfo.less";
import { projectTypeMap, projectUsageTypeMap } from "../common/constants";
import CompanyCollectionModal from "./components/companyCollectionModal";
import CrudViewBase from "../common/crud-view-base";
@@ -14,270 +17,426 @@
import { includePermission } from "../../utils/auth";
import { getClientOptions } from "../../api/business";
import { toOptionsData } from "../common/common_func";
import { exportPlan, exportProject, downloadProjectTemplate, importProject } from "../../api/export";
import {
  exportPlan,
  exportProject,
  downloadProjectTemplate,
  importProject,
} from "../../api/export";
const { Column } = Table;
const { Option } = Select;
const inputLongStyle = {
    padding: '1px 10px',
    width: '250px'
}
  padding: "1px 10px",
  width: "250px",
};
class Projects extends CrudViewBase {
  initListBody() {
    return {
      keyword: "",
      clientIds: null,
      projectTypes: null,
    };
  }
    initListBody() {
        return {
            keyword: '',
            clientIds: null,
            projectTypes: null
        }
    }
  initView() {
    this.getClientOptionsFunc();
    this.setState({
      clientOptions: [],
    });
  }
    initView() {
        this.getClientOptionsFunc()
  getClientOptionsFunc() {
    getClientOptions().then((res) => {
      if (res.data.status === "OK") {
        this.setState({
            clientOptions: []
        })
    }
          clientOptions: toOptionsData(res.data.data),
        });
      }
    });
  }
    getClientOptionsFunc() {
        getClientOptions().then(res => {
            if (res.data.status === 'OK') {
  getEntityList(pageInfo, listBody) {
    return getProjectList(pageInfo, listBody);
  }
  editEntity(data, isEdit) {
    return editProject(data, isEdit);
  }
  deleteEntities(ids) {
    return deleteProject(ids);
  }
  async exportEntities(listBody) {
    return exportProject(listBody);
  }
  // 下载导入模板
  downloadTemplate = () => {
    return downloadProjectTemplate();
  };
  // 上传文件并导入
  importEntities = (info) => {
    return importProject(info.file);
  };
  openCompanyInfo = (row) => {
    this.setState({
      currentRowData: row,
      showCompanyInfo: true,
    });
  };
  openProjectDetail = (row) => {
    this.setState({
      currentRowData: row,
      showProjectDetail: true,
    });
  };
  openProjectInfo = (row) => {
    this.setState({
      currentRowData: row,
      showProjectInfo: true,
    });
  };
  openProjectStatusSetting = (row) => {
    this.setState({
      currentRowData: row,
      showProjectStatusSetting: true,
    });
  };
  handleProjectStatusSettingCancel = () => {
    this.setState({
      showProjectStatusSetting: false,
      currentRowData: null,
    });
  };
  openPermissionSetting = (row) => {
    this.setState({
      currentRowData: row,
      showPermissionSetting: true,
    });
  };
  handlePermissionSettingCancel = () => {
    this.setState({
      showPermissionSetting: false,
      currentRowData: null,
    });
  };
  openDeviceUsage = (row) => {
    this.setState({
      currentRowData: row,
      showDeviceUsage: true,
    });
  };
  handleCompanyInfoCancel = () => {
    this.setState({
      showCompanyInfo: false,
      currentRowData: null,
    });
  };
  handleProjectDetailCancel = () => {
    this.setState({
      showProjectDetail: false,
      currentRowData: null,
    });
  };
  handleProjectInfoCancel = () => {
    this.setState({
      showProjectInfo: false,
      currentRowData: null,
    });
  };
  handleDeviceUsageCancel = () => {
    this.setState({
      showDeviceUsage: false,
      currentRowData: null,
    });
  };
  handlePermissionSettingOk = (formData) => {
  };
  handleStatusSettingOk = (formData) => {
  };
  render() {
    const { entities } = this.state;
    const title = (
      <div className="flex title">
        <div>
          <Input
            style={inputLongStyle}
            placeholder="请输入关键字"
            onChange={(e) => {
              this.handleListBodyChange("keyword", e.target.value);
            }}
            prefix={<Icon style={{ marginLeft: "4px" }} type="search" />}
            allowClear
          />
          &nbsp;
          <Select
            style={{
              width: 250,
            }}
            placeholder="项目类型"
            allowClear
            mode="multiple"
            onChange={(value) => {
              this.handleListBodyChange("projectTypes", value);
            }}
          >
            {projectTypeMap.toOptions().map((item, index) => (
              <Option value={item.value} key={index}>
                {item.label}
              </Option>
            ))}
          </Select>
          &nbsp; &nbsp;
          <Select
            style={{
              width: 250,
            }}
            placeholder="委托方"
            allowClear
            mode="multiple"
            onChange={(value) => {
              this.handleListBodyChange("clientIds", value);
            }}
          >
            {this.state.clientOptions &&
              this.state.clientOptions.map((item, index) => (
                <Option value={item.value} key={item.value}>
                  {item.label}
                </Option>
              ))}
          </Select>
        </div>
        &nbsp; &nbsp;
        <div className="right">
          {this.renderImportButton()}
          &nbsp; &nbsp;
          {this.renderExportButton()}
          &nbsp; &nbsp;
          {this.renderAddButton("project:add")}
          &nbsp; &nbsp;
          {this.renderBatchDeleteButton("project:delete")}
        </div>
      </div>
    );
    return (
      <div className="app-container">
        <Card title={title}>
          <Table
            bordered
            rowKey="id"
            rowSelection={{
              type: "checkbox",
              selectedRowKeys: this.state.selectedRowKeys,
              onChange: (selectedRowKeys, selectedRows) => {
                this.setState({
                    clientOptions: toOptionsData(res.data.data)
                })
            }
        })
    }
    getEntityList(pageInfo, listBody) {
        return getProjectList(pageInfo, listBody)
    }
    editEntity(data, isEdit) {
        return editProject(data, isEdit)
    }
    deleteEntities(ids) {
        return deleteProject(ids)
    }
    async exportEntities(listBody) {
        return exportProject(listBody)
    }
    // 下载导入模板
    downloadTemplate = () => {
        return downloadProjectTemplate()
    }
    // 上传文件并导入
    importEntities = (info) => {
        return importProject(info.file)
    }
    openCompanyInfo = (row) => {
        this.setState({
            currentRowData: row,
            showCompanyInfo: true
        })
    }
    openProjectDetail = (row) => {
        this.setState({
            currentRowData: row,
            showProjectDetail: true
        })
    }
    openProjectInfo = (row) => {
        this.setState({
            currentRowData: row,
            showProjectInfo: true
        })
    }
    openDeviceUsage = (row) => {
        this.setState({
            currentRowData: row,
            showDeviceUsage: true
        })
    }
    handleCompanyInfoCancel = () => {
        this.setState({
            showCompanyInfo: false,
            currentRowData: null
        })
    }
    handleProjectDetailCancel = () => {
        this.setState({
            showProjectDetail: false,
            currentRowData: null
        })
    }
    handleProjectInfoCancel = () => {
        this.setState({
            showProjectInfo: false,
            currentRowData: null
        })
    }
    handleDeviceUsageCancel = () => {
        this.setState({
            showDeviceUsage: false,
            currentRowData: null
        })
    }
    render() {
        const { entities } = this.state
        const title = (
            <div className="title flex">
                <div>
                    <Input
                        style={inputLongStyle}
                        placeholder="请输入关键字"
                        onChange={
                            (e) => {
                                this.handleListBodyChange('keyword', e.target.value)
                            }}
                        prefix={<Icon style={{ marginLeft: '4px' }} type="search" />}
                        allowClear
                    />
                    &nbsp;
                    <Select
                        style={{
                            width: 250,
                        }}
                        placeholder="项目类型"
                        allowClear
                        mode="multiple"
                        onChange={
                            (value) => {
                                this.handleListBodyChange('projectTypes', value)
                            }}
                    >
                        {projectTypeMap.toOptions().map((item, index) => (
                            <Option value={item.value} key={index}>{item.label}</Option>
                        ))}
                    </Select>
                    &nbsp;
                    &nbsp;
                    <Select
                        style={{
                            width: 250,
                        }}
                        placeholder="委托方"
                        allowClear
                        mode="multiple"
                        onChange={
                            (value) => {
                                this.handleListBodyChange('clientIds', value)
                            }
                        }
                    >
                        {this.state.clientOptions && this.state.clientOptions.map((item, index) => (
                            <Option value={item.value} key={item.value}>{item.label}</Option>
                        ))}
                    </Select>
                  selectedEntities: selectedRows,
                  selectedRowKeys: selectedRowKeys,
                });
              },
            }}
            dataSource={entities}
            scroll={{ x: "100%" }}
            pagination={false}
          >
            <Column
              title="序号"
              dataIndex="id"
              key="id"
              align="center"
              ellipsis={true}
            />
            <Column
              title="项目名称"
              dataIndex="name"
              key="name"
              align="center"
              width={300}
              ellipsis={true}
            />
            <Column
              title="委托方"
              key="client.name"
              dataIndex="client.name"
              width={150}
              align="center"
              ellipsis={true}
            />
            <Column
              title="项目类型"
              key="type"
              align="center"
              ellipsis={true}
              render={(text, row) => <span>{projectTypeMap[row.type]}</span>}
            />
            <Column
              title="用途类型"
              key="usageType"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>{projectUsageTypeMap[row.usageType]}</span>
              )}
            />
            <Column
              title="状态"
              key="status"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <span>{row.status === 1 ? "在建" : "完成"}</span>
              )}
            />
            <Column
              title="单位集合"
              key="companyInfo"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <div
                  className="link-btn"
                  onClick={this.openCompanyInfo.bind(null, row)}
                >
                  点击查看
                </div>
                &nbsp;
                &nbsp;
                <div className="right">
                    {this.renderImportButton()}
                    &nbsp;
                    &nbsp;
                    {this.renderExportButton()}
                    &nbsp;
                    &nbsp;
                    {this.renderAddButton("project:add")}
                    &nbsp;
                    &nbsp;
                    {this.renderBatchDeleteButton("project:delete")}
              )}
            />
            <Column
              title="信息集合"
              key="projectDetail"
              align="center"
              ellipsis={true}
              render={(text, row) => (
                <div
                  className="link-btn"
                  onClick={this.openProjectDetail.bind(null, row)}
                >
                  点击查看
                </div>
            </div>
        )
        return (
            <div className="app-container">
                <Card title={title}>
                    <Table
                        bordered
                        rowKey="id"
                        rowSelection={{
                            type: 'checkbox',
                            selectedRowKeys: this.state.selectedRowKeys,
                            onChange: (selectedRowKeys, selectedRows) => {
                                this.setState({
                                    selectedEntities: selectedRows,
                                    selectedRowKeys: selectedRowKeys
                                })
                            },
                        }}
                        dataSource={entities}
                        scroll={{ x: '100%' }}
                        pagination={false}>
                        <Column title="序号" dataIndex="id" key="id" align="center" ellipsis={true} />
                        <Column title="项目名称" dataIndex="name" key="name" align="center" width={300} ellipsis={true} />
                        <Column title="委托方" key="client.name" dataIndex="client.name" width={150} align="center" ellipsis={true} />
                        <Column title="项目类型" key="type" align="center" ellipsis={true} render={(text, row) => (
                            <span>{projectTypeMap[row.type]}</span>
                        )} />
                        <Column title="用途类型" key="usageType" align="center" ellipsis={true} render={(text, row) => (
                            <span>{projectUsageTypeMap[row.usageType]}</span>
                        )} />
                        <Column title="单位集合" key="companyInfo" align="center" ellipsis={true} render={(text, row) => (
                            <div className="link-btn" onClick={this.openCompanyInfo.bind(null, row)}>点击查看</div>
                        )} />
                        <Column title="信息集合" key="projectDetail" align="center" ellipsis={true} render={(text, row) => (
                            <div className="link-btn" onClick={this.openProjectDetail.bind(null, row)}>点击查看</div>
                        )} />
                        {/*<Column title="施工许可证号" key="constructionLicense" ellipsis={true} dataIndex="constructionLicense"*/}
                        {/*        align="center"/>*/}
                        {/*<Column title="工程造价(万元)" dataIndex="projectCost" key="projectCost" align="center" ellipsis={true}/>*/}
                        <Column title="最近一次检查时间" key="updateTime" align="center" ellipsis={true} />
                        <Column title="操作" key="action" width={420} align="center"
                            render={(text, row) => (
                                <span>
                                    {this.renderEditButton(row, "project:edit")}
                                    <Spacer />
                                    {this.renderDeleteButton(row, "project:delete")}
                                    <Spacer />
                                    <Button title="设备信息" onClick={this.openDeviceUsage.bind(null, row)} hidden={!includePermission("deviceUsage:*")} >设备信息</Button>
                                    <Spacer />
                                    <Button title="项目信息" onClick={this.openProjectInfo.bind(null, row)} hidden={!includePermission("projectInfo:*")}>项目信息</Button>
                                </span>
                            )} />
                    </Table>
                    <br />
                    {this.renderPagination()}
                </Card>
                <CompanyCollectionModal visible={this.state.showCompanyInfo}
                    currentRowData={this.state.currentRowData}
                    onCancel={this.handleCompanyInfoCancel} />
                <ProjectDetail visible={this.state.showProjectDetail}
                    currentRowData={this.state.currentRowData}
                    onCancel={this.handleProjectDetailCancel} />
              )}
            />
            {/*<Column title="施工许可证号" key="constructionLicense" ellipsis={true} dataIndex="constructionLicense"*/}
            {/*        align="center"/>*/}
            {/*<Column title="工程造价(万元)" dataIndex="projectCost" key="projectCost" align="center" ellipsis={true}/>*/}
            <Column
              title="最近一次检查时间"
              key="updateTime"
              align="center"
              ellipsis={true}
            />
            <Column
              title="操作"
              key="action"
              width={400}
              align="center"
              render={(text, row) => (
                <span>
                  {this.renderEditButton(row, "project:edit")}
                  <Spacer />
                  {this.renderDeleteButton(row, "project:delete")}
                  <Spacer />
                  <Button
                    title="设备信息"
                    onClick={this.openDeviceUsage.bind(null, row)}
                    hidden={!includePermission("deviceUsage:*")}
                  >
                    设备信息
                  </Button>
                  <Spacer />
                  <Button
                    title="项目信息"
                    onClick={this.openProjectInfo.bind(null, row)}
                    hidden={!includePermission("projectInfo:*")}
                  >
                    项目信息
                  </Button>
                  <Spacer />
                  <Button
                    title="权限设置"
                    style={{ marginTop: "10px" }}
                    onClick={this.openPermissionSetting.bind(null, row)}
                    hidden={!includePermission("projectInfo:*")}
                  >
                    权限设置
                  </Button>
                  <Spacer />
                  <Button
                    title="修改状态"
                    onClick={this.openProjectStatusSetting.bind(null, row)}
                    hidden={!includePermission("projectInfo:*")}
                  >
                    修改状态
                  </Button>
                </span>
              )}
            />
          </Table>
          <br />
          {this.renderPagination()}
        </Card>
        <CompanyCollectionModal
          visible={this.state.showCompanyInfo}
          currentRowData={this.state.currentRowData}
          onCancel={this.handleCompanyInfoCancel}
        />
        <ProjectDetail
          visible={this.state.showProjectDetail}
          currentRowData={this.state.currentRowData}
          onCancel={this.handleProjectDetailCancel}
        />
                <ProjectInfo visible={this.state.showProjectInfo}
                    currentRowData={this.state.currentRowData}
                    onCancel={this.handleProjectInfoCancel} />
                <DeviceUsage visible={this.state.showDeviceUsage}
                    currentRowData={this.state.currentRowData}
                    onCancel={this.handleDeviceUsageCancel} />
                <EditProjectForm
                    currentRowData={this.state.currentRowData}
                    wrappedComponentRef={formRef => this.editFormRef = formRef}
                    visible={this.state.editModalVisible}
                    confirmLoading={this.state.editModalLoading}
                    onCancel={this.handleEditEntityCancel}
                    onOk={this.handleEditEntityOk}
                />
            </div>
        );
    }
        <ProjectInfo
          visible={this.state.showProjectInfo}
          currentRowData={this.state.currentRowData}
          onCancel={this.handleProjectInfoCancel}
        />
        <DeviceUsage
          visible={this.state.showDeviceUsage}
          currentRowData={this.state.currentRowData}
          onCancel={this.handleDeviceUsageCancel}
        />
        <EditProjectForm
          currentRowData={this.state.currentRowData}
          wrappedComponentRef={(formRef) => (this.editFormRef = formRef)}
          visible={this.state.editModalVisible}
          confirmLoading={this.state.editModalLoading}
          onCancel={this.handleEditEntityCancel}
          onOk={this.handleEditEntityOk}
        />
        <EditProjectPermissionForm
          currentRowData={this.state.currentRowData}
          visible={this.state.showPermissionSetting}
          onCancel={this.handlePermissionSettingCancel}
          onOk={this.handlePermissionSettingOk}
        />
        <EditProjectStatusForm
          currentRowData={this.state.currentRowData}
          visible={this.state.showProjectStatusSetting}
          onCancel={this.handleProjectStatusSettingCancel}
          onOk={this.handleStatusSettingOk}
        />
      </div>
    );
  }
}
export default Projects;
estate-frontend-v2024/src/views/business/style/clientParams.less
New file
@@ -0,0 +1,29 @@
.container {
    padding-top: 24px;
    .item {
        display: flex;
        align-items: center;
        margin-bottom: 10px;
    }
    .label {
        width: 100px;
        text-align: right;
    }
    .value {
        .value-input {
            width: 160px;
            margin-left: 16px;
        }
    }
    .footerValue {
        display: flex;
        align-items: center;
        .value-input {
            width: 160px;
            margin-left: 16px;
        }
        >div:last-child {
            margin-left: 24px;
        }
    }
}
estate-frontend-v2024/src/views/common/crud-view-base.jsx
@@ -20,6 +20,14 @@
        selectedEntities: [],
        selectedRowKeys: [],
        // 重置密码模态框
        resetPasswordModalVisible: false,
        resetPasswordModalLoading: false,
        // 参数设置模态框
        parameterSettingModalVisible: false,
        parameterSettingModalLoading: false,
        // 编辑模态框
        editModalVisible: false,
        editModalLoading: false,
@@ -37,6 +45,12 @@
    // 编辑表单的引用
    editFormRef = null;
    // 重置密码表单的引用
    resetPasswordFormRef = null;
    // 参数设置表单的引用
    parameterSettingFormRef = null;
    // 组件挂载
    componentDidMount() {
@@ -144,6 +158,41 @@
            this.reloadEntities()
        })
    }
    // 处理启用禁用实体
    handleEnableDisableEntity = (row) => {
    };
    // 处理参数设置实体
    handleParameterSettingEntity = (row) => {
        this.setState({
            currentRowData: JSON.parse(JSON.stringify(row)),
            parameterSettingModalVisible: true,
        });
    };
    // 处理参数设置实体取消
    handleParameterSettingEntityCancel = _ => {
        this.setState({
            parameterSettingModalVisible: false,
        });
    };
    // 处理重置密码按钮实体
    handleResetPasswordEntity = (row) => {
        this.setState({
            currentRowData: JSON.parse(JSON.stringify(row)),
            resetPasswordModalVisible: true,
        });
    };
    // 处理重置密码实体取消
    handleResetPasswordEntityCancel = _ => {
        this.setState({
            resetPasswordModalVisible: false,
        });
    };
    // 处理编辑实体
    handleEditEntity = (row) => {
@@ -268,7 +317,7 @@
            if (err) {
                return;
            }
            console.log(this.editFormRef.state)
            this.setState({ editModalLoading: true, });
            let formState = this.editFormRef.state
            let action = formState.isEdit ? '编辑' : '添加';
@@ -296,6 +345,53 @@
    onEditSuccess = () => {
    }
    // 处理参数设置实体确认
    handleParameterSettingEntityOk = _ => {
        const { form } = this.parameterSettingFormRef.props;
        form.validateFields((err) => {
            if (err) {
                return;
            }
            console.log(this.parameterSettingFormRef.state)
            this.setState({ parameterSettingModalLoading: true, });
            let formState = this.parameterSettingFormRef.state
        });
    };
    // 处理参数设置实体成功
    onParameterSettingSuccess = () => {
    }
    // 渲染禁用/启用按钮
    renderEnableDisableButton(row, permission = null, disable = false) {
        return (
            <Button title={row.state === 1 ? "禁用" : "启用"} onClick={this.handleEnableDisableEntity.bind(null, row)}
                disabled={disable} hidden={!includePermission(permission)}>
                {row.state === 1 ? "禁用" : "启用"}
            </Button>
        );
    }
    // 渲染重置密码按钮
    renderResetPasswordButton(row, permission = null, disable = false) {
        return (
            <Button title="重置密码" onClick={this.handleResetPasswordEntity.bind(null, row)}
                disabled={disable} hidden={!includePermission(permission)}>
                重置密码
            </Button>
        );
    }
      // 渲染参数设置按钮
    renderParameterSettingButton(row, permission = null, disable = false) {
        return (
            <Button title="参数设置" onClick={this.handleParameterSettingEntity.bind(null, row)}
                disabled={disable} hidden={!includePermission(permission)}>
                参数设置
            </Button>
        );
    }
    // 渲染编辑按钮
    renderEditButton(row, permission = null, disable = false) {
        return (
estate-frontend-v2024/src/views/layout/Header/index.jsx
@@ -1,7 +1,17 @@
import React from "react";
import React, { useState } from "react";
import { connect } from "react-redux";
import { useHistory } from 'react-router-dom';
import { Icon, Menu, Dropdown, Modal, Layout, Avatar } from "antd";
import { useHistory } from "react-router-dom";
import {
  Icon,
  Menu,
  Dropdown,
  Modal,
  Layout,
  Avatar,
  Tabs,
  Radio,
  Input,
} from "antd";
import { Link } from "react-router-dom";
import { logout, getUserInfo } from "@/store/actions";
import FullScreen from "@/components/FullScreen";
@@ -10,6 +20,8 @@
import BreadCrumb from "@/components/BreadCrumb";
import "./index.less";
const { Header } = Layout;
const { TabPane } = Tabs;
const { Search } = Input;
const LayoutHeader = (props) => {
  const history = useHistory();
@@ -22,6 +34,7 @@
    showSettings,
    fixedHeader,
  } = props;
  const [visible, setVisible] = useState(false);
  // token && getUserInfo(token);
  const handleLogout = (token) => {
    Modal.confirm({
@@ -44,19 +57,15 @@
    }
  };
  const goToPersonal = () => {
    history.push('/personal')
  }
    history.push("/personal");
  };
  const menu = (
    <Menu onClick={onClick}>
      <Menu.Item key="dashboard">
        <Link to="/dashboard">智慧大屏</Link>
      </Menu.Item>
      <Menu.Item key="project">
        <a
          onClick={goToPersonal}
        >
          个人信息
        </a>
        <a onClick={goToPersonal}>个人信息</a>
      </Menu.Item>
      <Menu.Divider />
      <Menu.Item key="logout">注销</Menu.Item>
@@ -81,6 +90,20 @@
    }
    return styles;
  };
  const accountList = [
    {
      id: 1,
      name: "委托方1",
    },
    {
      id: 2,
      name: "委托方2",
    },
  ];
  const [selectedAccount, setSelectedAccount] = useState("");
  return (
    <>
      {/* 这里是仿照antd pro的做法,如果固定header,
@@ -93,6 +116,14 @@
        <Hamburger />
        <BreadCrumb />
        <div className="right-menu">
          <div className="platform-name" onClick={() => setVisible(true)}>
            <Icon
              type="fund"
              theme="filled"
              style={{ fontSize: 24, marginRight: 8 }}
            />
            智慧工程安全监管平台
          </div>
          <FullScreen />
          {showSettings ? <Settings /> : null}
          <div className="dropdown-wrap">
@@ -105,6 +136,54 @@
          </div>
        </div>
      </Header>
      <Modal
        title="选择登录端口"
        visible={visible}
        width={450}
        onCancel={() => setVisible(false)}
        onOk={() => setVisible(false)}
      >
        <Tabs defaultActiveKey="1">
          <TabPane tab="委托方" key="1">
            <div className="box">
              <Search
                placeholder="请输入委托方名称"
                enterButton="搜索"
                onSearch={(value) => console.log(value)}
              />
              {accountList.map((item) => (
                <div
                  key={item.id}
                  className="item"
                  onClick={() => setSelectedAccount(item.id)}
                >
                  <div className="name">{item.name}</div>
                  <Radio checked={selectedAccount === item.id} />
                </div>
              ))}
            </div>
          </TabPane>
          <TabPane tab="项目" key="2">
            <div className="box">
               <Search
                placeholder="请输入项目名称"
                enterButton="搜索"
                onSearch={(value) => console.log(value)}
              />
              {accountList.map((item) => (
                <div
                  key={item.id}
                  className="item"
                  onClick={() => setSelectedAccount(item.id)}
                >
                  <div className="name">{item.name}</div>
                  <Radio checked={selectedAccount === item.id} />
                </div>
              ))}
            </div>
          </TabPane>
        </Tabs>
      </Modal>
    </>
  );
};
estate-frontend-v2024/src/views/layout/Header/index.less
@@ -7,6 +7,16 @@
  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
  .right-menu {
    float: right;
    .platform-name {
      display: inline-flex;
      align-items: center;
      font-size: 16px;
      font-weight: 500;
      color: #303133;
      margin-right: 24px;
      vertical-align: middle;
      cursor: pointer;
    }
    .dropdown-wrap {
      cursor: pointer;
      display: inline-block;
@@ -28,3 +38,18 @@
  top: 0;
  right: 0;
}
.box {
  padding: 0 20px;
  .item {
    width: 100%;
    padding: 0 20px;
    margin-top: 16px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 36px;
    cursor: pointer;
  }
}
estate-frontend-v2024/src/views/screenSetting/accidentMessageSetting.jsx
New file
@@ -0,0 +1,215 @@
import React from "react";
import { Card, Divider, Icon, Input, Select, Table } from "antd";
import { deleteDevice, editDevice, getDevicesList } from "@/api/devices";
import EditAccountMessageForm from "./forms/edit-accidentMessage-form";
import "./style/index.less";
import CrudViewBase from "../common/crud-view-base";
const { Column } = Table;
const { Option } = Select;
const inputLongStyle = {
  padding: "1px 10px",
  width: "250px",
};
class AccidentMessageSetting extends CrudViewBase {
  state = {
    ...this.state,
    entities: [],
  };
  initListBody() {
    return {
      name: "",
      keyword: "",
      deviceType: "",
    };
  }
  // 重写处理listBody变化的方法,当deviceType变化时加载表单
  handleListBodyChange = (key, value) => {
    this.setState(
      (prevState) => {
        const newListBody = { ...prevState.listBody, [key]: value };
        return { listBody: newListBody };
      },
      () => {
        this.reloadEntities();
      }
    );
  };
  getEntityList(pageInfo, listBody) {
    return getDevicesList(pageInfo, listBody);
  }
  editEntity(data, isEdit) {
    return editDevice(data, isEdit);
  }
  deleteEntities(ids) {
    return deleteDevice(ids);
  }
  // 处理重置密码实体确认
  handleResetPasswordEntityOk = (_) => {
    const { form } = this.resetPasswordFormRef.props;
    form.validateFields((err) => {
      if (err) {
        return;
      }
      this.setState({ resetPasswordModalLoading: true });
      let formState = this.resetPasswordFormRef.state;
      console.log(formState.editableData);
      // this.editEntity(formState.editableData, formState.isEdit)
      //   .then((response) => {
      //     if (response.data.status === "OK") {
      //       form.resetFields();
      //       message.success(action + "成功!");
      //       this.setState({
      //         resetPasswordModalVisible: false,
      //         resetPasswordModalLoading: false,
      //       });
      //       this.onResetPasswordSuccess();
      //       this.reloadEntities();
      //     } else {
      //       this.setState({ resetPasswordModalLoading: false });
      //       message.success(response.data.errorMsg || action + "失败,请重试");
      //     }
      //   })
      //   .catch((e) => {
      //     message.success(action + "失败,请重试! " + e.message);
      //   });
    });
  };
  render() {
    const { entities } = this.state;
    const title = (
      <div className="flex title">
        <div>
          <Input
            style={inputLongStyle}
            placeholder="请输入姓名"
            onChange={(e) => {
              this.handleListBodyChange("keyword", e.target.value);
            }}
            prefix={<Icon style={{ marginLeft: "4px" }} type="search" />}
            allowClear
          />
          &nbsp;
          <Select
            style={{
              width: 250,
            }}
            placeholder="账号级别"
            onChange={(value) => {
              this.handleListBodyChange("deviceType", value);
            }}
          >
            <Option value={1}>委托方</Option>
            <Option value={2}>项目</Option>
          </Select>
          &nbsp; &nbsp;
        </div>
        &nbsp; &nbsp;
        <div className="right">{this.renderAddButton("device:add")}</div>
      </div>
    );
    return (
      <div className="app-container">
        <Card title={title}>
          <Table
            bordered
            rowKey="id"
            dataSource={entities}
            pagination={false}
            scroll={{ x: "max-content" }}
          >
            <Column
              title="序号"
              width={125}
              dataIndex="id"
              key="id"
              align="center"
            />
            <Column
              title="标题"
              width={125}
              dataIndex="name"
              key="name"
              align="center"
            />
            <Column
              title="事故类型"
              width={125}
              dataIndex="account"
              key="account"
              align="center"
            />
            <Column
              title="发生地点"
              width={125}
              dataIndex="accountType"
              key="accountType"
              align="center"
            />
            <Column
              title="伤亡情况"
              width={125}
              dataIndex="casualties"
              key="casualties"
              align="center"
            />
            <Column
              title="发生时间"
              dataIndex="date"
              key="date"
              align="center"
            />
            <Column
              title="状态"
              key="state"
              align="center"
              render={(text, row) => (
                <span style={{ color: row.state ? "yellow" : "inherit" }}>
                  {row.state ? "启用" : "禁用"}
                </span>
              )}
            />
            <Column
              title="操作"
              key="action"
              width={260}
              fixed="right"
              align="center"
              render={(text, row) => (
                <span>
                  {this.renderEnableDisableButton(row, "device:edit")}
                  <Divider type="vertical" />
                  {this.renderEditButton(row, "device:edit")}
                  <Divider type="vertical" />
                  {this.renderDeleteButton(row, "device:delete")}
                </span>
              )}
            />
          </Table>
          <br />
          {this.renderPagination()}
        </Card>
        <EditAccountMessageForm
          currentRowData={this.state.currentRowData}
          wrappedComponentRef={(formRef) => (this.editFormRef = formRef)}
          visible={this.state.editModalVisible}
          confirmLoading={this.state.editModalLoading}
          onCancel={this.handleEditEntityCancel}
          onOk={this.handleEditEntityOk}
        />
      </div>
    );
  }
}
export default AccidentMessageSetting;
estate-frontend-v2024/src/views/screenSetting/accidentTypeSetting.jsx
New file
@@ -0,0 +1,124 @@
import React from "react";
import { Card, Divider, Icon, Input, Table } from "antd";
import { deleteDevice, editDevice, getDevicesList } from "@/api/devices";
import EditAccidentTypeForm from "./forms/edit-accidentType-form";
import "./style/index.less";
import CrudViewBase from "../common/crud-view-base";
const { Column } = Table;
const inputLongStyle = {
  padding: "1px 10px",
  width: "250px",
};
class AccidentTypeSetting extends CrudViewBase {
  state = {
    ...this.state,
    entities: [],
  };
  initListBody() {
    return {
      keyword: "",
      deviceType: "",
    };
  }
  // 重写处理listBody变化的方法,当deviceType变化时加载表单
  handleListBodyChange = (key, value) => {
    this.setState(
      (prevState) => {
        const newListBody = { ...prevState.listBody, [key]: value };
        return { listBody: newListBody };
      },
      () => {
        this.reloadEntities();
      }
    );
  };
  getEntityList(pageInfo, listBody) {
    return getDevicesList(pageInfo, listBody);
  }
  editEntity(data, isEdit) {
    return editDevice(data, isEdit);
  }
  deleteEntities(ids) {
    return deleteDevice(ids);
  }
  render() {
    const { entities } = this.state;
    const title = (
      <div className="flex title">
        <div>
          <Input
            style={inputLongStyle}
            placeholder="请输入分类"
            onChange={(e) => {
              this.handleListBodyChange("keyword", e.target.value);
            }}
            prefix={<Icon style={{ marginLeft: "4px" }} type="search" />}
            allowClear
          />
        </div>
        &nbsp; &nbsp;
        <div className="right">{this.renderAddButton("device:add")}</div>
      </div>
    );
    return (
      <div className="app-container">
        <Card title={title}>
          <Table
            bordered
            rowKey="id"
            dataSource={entities}
            pagination={false}
            scroll={{ x: "max-content" }}
          >
            <Column
              title="序号"
              dataIndex="id"
              key="id"
              align="center"
            />
            <Column
              title="事故类型"
              dataIndex="name"
              key="name"
              align="center"
            />
            <Column
              title="操作"
              key="action"
              width={360}
              align="center"
              render={(text, row) => (
                <span>
                  {this.renderEditButton(row, "device:edit")}
                  <Divider type="vertical" />
                  {this.renderDeleteButton(row, "device:delete")}
                </span>
              )}
            />
          </Table>
          <br />
          {this.renderPagination()}
        </Card>
        <EditAccidentTypeForm
          currentRowData={this.state.currentRowData}
          wrappedComponentRef={(formRef) => (this.editFormRef = formRef)}
          visible={this.state.editModalVisible}
          confirmLoading={this.state.editModalLoading}
          onCancel={this.handleEditEntityCancel}
          onOk={this.handleEditEntityOk}
        />
      </div>
    );
  }
}
export default AccidentTypeSetting;
estate-frontend-v2024/src/views/screenSetting/accountSetting.jsx
New file
@@ -0,0 +1,235 @@
import React from "react";
import { Card, Divider, Icon, Input, Select, Table } from "antd";
import {
  deleteDevice,
  editDevice,
  getDevicesList,
  loadDeviceForm,
} from "@/api/devices";
import EditAccountForm from "./forms/edit-account-form";
import ResetPasswordForm from "./forms/reset-password-form";
import "./style/index.less";
import CrudViewBase from "../common/crud-view-base";
const { Column } = Table;
const { Option } = Select;
const inputLongStyle = {
  padding: "1px 10px",
  width: "250px",
};
class AccountSetting extends CrudViewBase {
  state = {
    ...this.state,
    entities: [],
  };
  initListBody() {
    return {
      name: "",
      keyword: "",
      deviceType: "",
    };
  }
  // 重写处理listBody变化的方法,当deviceType变化时加载表单
  handleListBodyChange = (key, value) => {
    this.setState(
      (prevState) => {
        const newListBody = { ...prevState.listBody, [key]: value };
        return { listBody: newListBody };
      },
      () => {
        this.reloadEntities();
      }
    );
  };
  getEntityList(pageInfo, listBody) {
    return getDevicesList(pageInfo, listBody);
  }
  editEntity(data, isEdit) {
    return editDevice(data, isEdit);
  }
  deleteEntities(ids) {
    return deleteDevice(ids);
  }
  // 处理重置密码实体确认
  handleResetPasswordEntityOk = (_) => {
    const { form } = this.resetPasswordFormRef.props;
    form.validateFields((err) => {
      if (err) {
        return;
      }
      this.setState({ resetPasswordModalLoading: true });
      let formState = this.resetPasswordFormRef.state;
      console.log(formState.editableData);
      // this.editEntity(formState.editableData, formState.isEdit)
      //   .then((response) => {
      //     if (response.data.status === "OK") {
      //       form.resetFields();
      //       message.success(action + "成功!");
      //       this.setState({
      //         resetPasswordModalVisible: false,
      //         resetPasswordModalLoading: false,
      //       });
      //       this.onResetPasswordSuccess();
      //       this.reloadEntities();
      //     } else {
      //       this.setState({ resetPasswordModalLoading: false });
      //       message.success(response.data.errorMsg || action + "失败,请重试");
      //     }
      //   })
      //   .catch((e) => {
      //     message.success(action + "失败,请重试! " + e.message);
      //   });
    });
  };
  render() {
    const { entities } = this.state;
    const title = (
      <div className="flex title">
        <div>
          <Input
            style={inputLongStyle}
            placeholder="请输入姓名"
            onChange={(e) => {
              this.handleListBodyChange("keyword", e.target.value);
            }}
            prefix={<Icon style={{ marginLeft: "4px" }} type="search" />}
            allowClear
          />
          &nbsp;
          <Input
            style={inputLongStyle}
            placeholder="请输入委托方/项目名称"
            onChange={(e) => {
              this.handleListBodyChange("keyword", e.target.value);
            }}
            prefix={<Icon style={{ marginLeft: "4px" }} type="search" />}
            allowClear
          />
          &nbsp;
          <Select
            style={{
              width: 250,
            }}
            placeholder="账号级别"
            onChange={(value) => {
              this.handleListBodyChange("deviceType", value);
            }}
          >
            <Option value={1}>委托方</Option>
            <Option value={2}>项目</Option>
          </Select>
          &nbsp; &nbsp;
        </div>
        &nbsp; &nbsp;
        <div className="right">{this.renderAddButton("device:add")}</div>
      </div>
    );
    return (
      <div className="app-container">
        <Card title={title}>
          <Table
            bordered
            rowKey="id"
            dataSource={entities}
            pagination={false}
            scroll={{ x: "max-content" }}
          >
            <Column
              title="序号"
              width={125}
              dataIndex="id"
              key="id"
              align="center"
            />
            <Column
              title="姓名"
              width={125}
              dataIndex="name"
              key="name"
              align="center"
            />
            <Column
              title="账号"
              width={125}
              dataIndex="account"
              key="account"
              align="center"
            />
            <Column
              title="账号级别"
              width={125}
              dataIndex="accountType"
              key="accountType"
              align="center"
              render={(text, row) => (
                <span>{row.accountType === 1 ? "委托方" : "项目"}</span>
              )}
            />
            <Column title="关联委托方/项目" key="type" align="center" />
            <Column
              title="状态"
              key="state"
              align="center"
              render={(text, row) => (
                <span style={{ color: row.state ? "yellow" : "inherit" }}>
                  {row.state ? "启用" : "禁用"}
                </span>
              )}
            />
            <Column
              title="操作"
              key="action"
              width={400}
              fixed="right"
              align="center"
              render={(text, row) => (
                <span>
                  {this.renderEnableDisableButton(row, "device:edit")}
                  <Divider type="vertical" />
                  {this.renderResetPasswordButton(row, "device:delete")}
                  <Divider type="vertical" />
                  {this.renderEditButton(row, "device:edit")}
                  <Divider type="vertical" />
                  {this.renderDeleteButton(row, "device:delete")}
                </span>
              )}
            />
          </Table>
          <br />
          {this.renderPagination()}
        </Card>
        <EditAccountForm
          currentRowData={this.state.currentRowData}
          wrappedComponentRef={(formRef) => (this.editFormRef = formRef)}
          visible={this.state.editModalVisible}
          confirmLoading={this.state.editModalLoading}
          onCancel={this.handleEditEntityCancel}
          onOk={this.handleEditEntityOk}
        />
        <ResetPasswordForm
          currentRowData={this.state.currentRowData}
          wrappedComponentRef={(formRef) =>
            (this.resetPasswordFormRef = formRef)
          }
          visible={this.state.resetPasswordModalVisible}
          confirmLoading={this.state.resetPasswordModalLoading}
          onCancel={this.handleResetPasswordEntityCancel}
          onOk={this.handleResetPasswordEntityOk}
        />
      </div>
    );
  }
}
export default AccountSetting;
estate-frontend-v2024/src/views/screenSetting/forms/edit-accidentMessage-form.jsx
New file
@@ -0,0 +1,264 @@
import React from "react";
import {
  Form,
  Input,
  Modal,
  Select,
  DatePicker,
  Cascader,
  Switch,
  Upload,
  Icon,
} from "antd";
import "../style/index.less";
import moment from "moment/moment";
import { checkFileSize } from "../../common/common_func";
import EditFormBase from "../../common/edit-form-base";
import { inputLongStyle } from "../../common/constants";
import { EditorState, convertToRaw } from "draft-js";
import { Editor } from "react-draft-wysiwyg";
import draftToHtml from "draftjs-to-html";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
const { Option } = Select;
function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}
class EditAccountMessageForm extends EditFormBase {
  initEditableData() {
    return {
      title: "",
      type: 1,
      casualties: "",
      description: "",
      date: null,
      detail: "",
      status: 1,
      city: "",
      file: [],
      previewVisible: false,
      previewImage: "",
      editorState: EditorState.createEmpty(),
    };
  }
  onEditorStateChange = (editorState) => {
    this.setState({
      editableData: {
        ...this.state.editableData,
        editorState,
        detail: draftToHtml(convertToRaw(editorState.getCurrentContent())),
      },
    });
  };
  handleCancel = () =>
    this.setState({
      editableData: {
        ...this.state.editableData,
        previewVisible: false,
        previewImage: "",
      },
    });
  handlePreview = async (file) => {
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj);
    }
    this.setState({
      editableData: {
        ...this.state.editableData,
        previewVisible: true,
        previewImage: file.url || file.preview,
      },
    });
  };
  render() {
    const { visible, onCancel, onOk, form } = this.props;
    const { getFieldDecorator } = form;
    const {
      title,
      type,
      casualties,
      description,
      date,
      detail,
      status,
      city,
      file,
      editorState,
      previewVisible,
      previewImage,
    } = this.state.editableData;
    const uploadButton = (
      <div>
        <Icon type="plus" />
      </div>
    );
    return (
      <Modal
        title={this.state.isEdit ? "编辑事故案例" : "添加事故案例"}
        visible={visible}
        onCancel={onCancel}
        width={1000}
        onOk={onOk}
        destroyOnClose
      >
        <Form
          labelCol={{ style: { width: "100%", height: "30px" } }}
          labelAlign="left"
        >
          <div className="grid grid-1-1-1">
            <Form.Item label="标题">
              {getFieldDecorator("title", {
                rules: [{ required: true, message: "请输入标题!" }],
                initialValue: title,
                onChange: this.handleFieldChange("title"),
              })(<Input style={inputLongStyle} placeholder="请输入标题" />)}
            </Form.Item>
            <Form.Item label="类别">
              {getFieldDecorator("type", {
                rules: [{ required: true, message: "请选择类别!" }],
                initialValue: type,
                onChange: this.handleFieldChange("type"),
              })(
                <Select style={inputLongStyle} placeholder="请选择关联委托方">
                  <Option value={1}>委托方1</Option>
                  <Option value={2}>委托方2</Option>
                </Select>,
              )}
            </Form.Item>
            <Form.Item label="发生城市">
              {getFieldDecorator("city", {
                initialValue: city,
                onChange: this.handleFieldChange("city"),
                rules: [{ required: true, message: "请选择发生城市!" }],
              })(
                <Cascader
                  style={{ width: "250px" }}
                  options={[
                    {
                      value: "1",
                      label: "北京",
                    },
                    {
                      value: "2",
                      label: "上海",
                    },
                  ]}
                  expandTrigger="hover"
                />,
              )}
            </Form.Item>
            <Form.Item label="造成伤亡情况">
              {getFieldDecorator("casualties", {
                rules: [{ required: true, message: "请选择启用状态!" }],
                initialValue: casualties,
                onChange: this.handleFieldChange("casualties"),
              })(
                <Input
                  style={inputLongStyle}
                  placeholder="请输入造成伤亡情况"
                />,
              )}
            </Form.Item>
            <Form.Item label="封面图">
              {getFieldDecorator("file", {
                valuePropName: "file",
                // getValueFromEvent: singleFile,
                initialValue: file,
                rules: [{ required: true, message: "请上传封面图" }],
              })(
                <div>
                  <Upload
                    disabled={this.uploading}
                    name={"file"}
                    maxCount={1}
                    listType="picture-card"
                    multiple={false}
                    customRequest={this.uploadAttachment.bind(null, "file")}
                    onRemove={() => {
                      this.setFieldValue("file", []);
                    }}
                    onPreview={this.handlePreview}
                    beforeUpload={checkFileSize}
                    accept="image/*"
                  >
                    {(!file || file.length === 0) ? uploadButton : null}
                  </Upload>
                  <Modal
                    visible={previewVisible}
                    footer={null}
                    onCancel={this.handleCancel}
                  >
                    <img
                      alt="example"
                      style={{ width: "100%" }}
                      src={previewImage}
                    />
                  </Modal>
                </div>,
              )}
            </Form.Item>
            <Form.Item label="情况简述">
              {getFieldDecorator("description", {
                rules: [{ required: true, message: "请输入情况简述!" }],
                initialValue: description,
                onChange: this.handleFieldChange("description"),
              })(<Input style={inputLongStyle} placeholder="请输入情况简述" />)}
            </Form.Item>
            <Form.Item label="发生时间">
              {getFieldDecorator("date", {
                rules: [{ required: true, message: "请输入日期" }],
                initialValue: date ? moment(date) : null,
                onChange: this.handleDateFieldChange("date"),
              })(
                <DatePicker style={{ width: "250px" }} format={"YYYY-MM-DD"} />,
              )}
            </Form.Item>
          </div>
          <Form.Item label="详情">
            {getFieldDecorator("detail", {
              rules: [{ required: true, message: "请输入详情" }],
              initialValue: detail,
              onChange: this.handleFieldChange("detail"),
            })(
              <div style={{ marginTop: 10 }}>
                <Editor
                  editorState={editorState}
                  onEditorStateChange={this.onEditorStateChange}
                  wrapperClassName="wrapper-class"
                  editorClassName="editor-class"
                  toolbarClassName="toolbar-class"
                  localization={{ locale: "zh" }}
                />
              </div>,
            )}
          </Form.Item>
          <Form.Item label="启用状态">
            {getFieldDecorator("status", {
              rules: [{ required: true, message: "请选择启用状态!" }],
              initialValue: status,
              onChange: this.handleFieldChange("status"),
            })(<Switch checked={status === 1} />)}
          </Form.Item>
        </Form>
      </Modal>
    );
  }
}
export default Form.create({ name: "EditAccountMessageForm" })(
  EditAccountMessageForm,
);
estate-frontend-v2024/src/views/screenSetting/forms/edit-accidentType-form.jsx
New file
@@ -0,0 +1,40 @@
import React from "react";
import { Form, Input, Modal } from "antd";
import "../style/index.less";
import EditFormBase from "../../common/edit-form-base";
import { inputLongStyle } from "../../common/constants";
class EditDeviceForm extends EditFormBase {
  initEditableData() {
    return {
      name: "",
    };
  }
  render() {
    const { visible, onCancel, onOk, form } = this.props;
    const { getFieldDecorator } = form;
    const { name } = this.state.editableData;
    return (
      <Modal
        title={this.state.isEdit ? "编辑分类" : "添加分类"}
        visible={visible}
        onCancel={onCancel}
        onOk={onOk}
        destroyOnClose
      >
        <Form {...this.formItemLayout}>
          <Form.Item label="分类名称">
            {getFieldDecorator("name", {
              rules: [{ required: true, message: "请输入分类名称!" }],
              initialValue: name,
              onChange: this.handleFieldChange("name"),
            })(<Input style={inputLongStyle} placeholder="请输入分类名称" />)}
          </Form.Item>
        </Form>
      </Modal>
    );
  }
}
export default Form.create({ name: "EditDeviceForm" })(EditDeviceForm);
estate-frontend-v2024/src/views/screenSetting/forms/edit-account-form.jsx
New file
@@ -0,0 +1,96 @@
import React from "react";
import { Form, Input, Modal, Select, Switch, Radio } from "antd";
import "../style/index.less";
import EditFormBase from "../../common/edit-form-base";
import {  inputLongStyle } from "../../common/constants";
const { Option } = Select;
class EditDeviceForm extends EditFormBase {
  initEditableData() {
    return {
      name: "",
      type: 1,
      status: 1,
      accountType: 1,
      account: "",
      password: "",
    };
  }
  render() {
    const { visible, onCancel, onOk, form } = this.props;
    const { getFieldDecorator } = form;
    const { name, status, account, password, type, accountType } = this.state.editableData;
    return (
      <Modal
        title={this.state.isEdit ? "编辑账号" : "添加账号"}
        visible={visible}
        onCancel={onCancel}
        onOk={onOk}
        destroyOnClose
      >
        <Form {...this.formItemLayout}>
          <Form.Item label="姓名">
            {getFieldDecorator("name", {
              rules: [{ required: true, message: "请输入姓名!" }],
              initialValue: name,
              onChange: this.handleFieldChange("name"),
            })(<Input style={inputLongStyle} placeholder="请输入姓名" />)}
          </Form.Item>
          <Form.Item label="级别">
            {getFieldDecorator("type", {
              rules: [{ required: true, message: "请选择级别!" }],
              initialValue: type,
              onChange: this.handleFieldChange("type"),
            })(
              <Radio.Group style={inputLongStyle}>
                <Radio value={1}>委托方</Radio>
                <Radio value={2}>项目</Radio>
              </Radio.Group>
            )}
          </Form.Item>
          <Form.Item label="关联委托方">
            {getFieldDecorator("accountType", {
              rules: [{ required: true, message: "请选择关联委托方!" }],
              initialValue: accountType,
              onChange: this.handleFieldChange("accountType"),
            })(
              <Select style={inputLongStyle} mode="multiple" placeholder="请选择关联委托方">
                <Option value={1}>委托方1</Option>
                <Option value={2}>委托方2</Option>
              </Select>
            )}
          </Form.Item>
          <Form.Item label="启用状态">
            {getFieldDecorator("status", {
              rules: [{ required: true, message: "请选择启用状态!" }],
              initialValue: status,
              onChange: this.handleFieldChange("status"),
            })(<Switch checked={status === 1} />)}
          </Form.Item>
          {!this.state.isEdit && (
            <Form.Item label="登录账号">
              {getFieldDecorator("account", {
                rules: [{ required: true, message: "请输入登录账号!" }],
                initialValue: account,
                onChange: this.handleFieldChange("account"),
              })(<Input style={inputLongStyle} placeholder="请输入登录账号" />)}
            </Form.Item>
          )}
          {!this.state.isEdit && (
            <Form.Item label="密码">
              {getFieldDecorator("password", {
                rules: [{ required: true, message: "请输入密码!" }],
                initialValue: password,
                onChange: this.handleFieldChange("password"),
              })(<Input style={inputLongStyle} placeholder="请输入密码" />)}
            </Form.Item>
          )}
        </Form>
      </Modal>
    );
  }
}
export default Form.create({ name: "EditDeviceForm" })(EditDeviceForm);
estate-frontend-v2024/src/views/screenSetting/forms/reset-password-form.jsx
New file
@@ -0,0 +1,48 @@
import React from "react";
import { Form, Input, Modal,  } from "antd";
import BaseForm from "../../common/edit-form-base";
class ResetPasswordForm extends BaseForm {
  initEditableData() {
    return {
      password: "",
      confirmPassword: "",
    };
  }
  render() {
    const { visible, onCancel, onOk, form, confirmLoading } = this.props;
    const { getFieldDecorator } = form;
    const { password, confirmPassword } = this.state.editableData;
    return (
      <Modal
        title="重置密码"
        visible={visible}
        onCancel={onCancel}
        onOk={onOk}
        confirmLoading={confirmLoading}
      >
        <Form {...this.formItemLayout}>
          <Form.Item label="新密码:">
            {getFieldDecorator("password", {
              rules: [{ required: true, message: "请输入新密码!" }],
              initialValue: password,
              onChange: this.handleFieldChange("password"),
            })(<Input placeholder="请输入新密码" />)}
          </Form.Item>
          <Form.Item label="确认密码:">
            {getFieldDecorator("confirmPassword", {
              rules: [{ required: true, message: "请输入确认密码!" }],
              initialValue: confirmPassword,
              onChange: this.handleFieldChange("confirmPassword"),
            })(<Input placeholder="请输入确认密码" />)}
          </Form.Item>
        </Form>
      </Modal>
    );
  }
}
export default Form.create({ name: "ResetPasswordForm" })(ResetPasswordForm);
estate-frontend-v2024/src/views/screenSetting/style/index.less
New file
@@ -0,0 +1,19 @@
.title {
  display: flex;
  align-items: center;
}
.grid {
  display: grid;
}
.grid-1-1-1 {
  grid-template-columns: 1fr 1fr 1fr ;
}
.editor-class{
  min-height: 300px;
  max-height: 300px;
  border: 1px solid #F1F1F1;
  border-top: none;
  margin-top: -5px;
  padding: 0 10px;
}
estate-frontend-v2024/src/views/standard/forms/edit-position-form.jsx
New file
@@ -0,0 +1,40 @@
import React from "react";
import { Form, Input, Modal } from "antd";
import "../style/standard.less";
import EditFormBase from "../../common/edit-form-base";
import { inputLongStyle } from "../../common/constants";
class EditDeviceForm extends EditFormBase {
  initEditableData() {
    return {
      name: "",
    };
  }
  render() {
    const { visible, onCancel, onOk, form } = this.props;
    const { getFieldDecorator } = form;
    const { name } = this.state.editableData;
    return (
      <Modal
        title={this.state.isEdit ? "编辑岗位" : "添加岗位"}
        visible={visible}
        onCancel={onCancel}
        onOk={onOk}
        destroyOnClose
      >
        <Form {...this.formItemLayout}>
          <Form.Item label="岗位名称">
            {getFieldDecorator("name", {
              rules: [{ required: true, message: "请输入岗位名称!" }],
              initialValue: name,
              onChange: this.handleFieldChange("name"),
            })(<Input style={inputLongStyle} placeholder="请输入岗位名称" />)}
          </Form.Item>
        </Form>
      </Modal>
    );
  }
}
export default Form.create({ name: "EditDeviceForm" })(EditDeviceForm);
estate-frontend-v2024/src/views/standard/position.jsx
New file
@@ -0,0 +1,124 @@
import React from "react";
import { Card, Divider, Icon, Input, Table } from "antd";
import { deleteDevice, editDevice, getDevicesList } from "@/api/devices";
import EditPositionForm from "./forms/edit-position-form";
import "./style/standard.less";
import CrudViewBase from "../common/crud-view-base";
const { Column } = Table;
const inputLongStyle = {
  padding: "1px 10px",
  width: "250px",
};
class PositionSetting extends CrudViewBase {
  state = {
    ...this.state,
    entities: [],
  };
  initListBody() {
    return {
      keyword: "",
      deviceType: "",
    };
  }
  // 重写处理listBody变化的方法,当deviceType变化时加载表单
  handleListBodyChange = (key, value) => {
    this.setState(
      (prevState) => {
        const newListBody = { ...prevState.listBody, [key]: value };
        return { listBody: newListBody };
      },
      () => {
        this.reloadEntities();
      }
    );
  };
  getEntityList(pageInfo, listBody) {
    return getDevicesList(pageInfo, listBody);
  }
  editEntity(data, isEdit) {
    return editDevice(data, isEdit);
  }
  deleteEntities(ids) {
    return deleteDevice(ids);
  }
  render() {
    const { entities } = this.state;
    const title = (
      <div className="flex title">
        <div>
          <Input
            style={inputLongStyle}
            placeholder="请输入岗位"
            onChange={(e) => {
              this.handleListBodyChange("keyword", e.target.value);
            }}
            prefix={<Icon style={{ marginLeft: "4px" }} type="search" />}
            allowClear
          />
        </div>
        &nbsp; &nbsp;
        <div className="right">{this.renderAddButton("device:add")}</div>
      </div>
    );
    return (
      <div className="app-container">
        <Card title={title}>
          <Table
            bordered
            rowKey="id"
            dataSource={entities}
            pagination={false}
            scroll={{ x: "max-content" }}
          >
            <Column
              title="序号"
              dataIndex="id"
              key="id"
              align="center"
            />
            <Column
              title="岗位名称"
              dataIndex="name"
              key="name"
              align="center"
            />
            <Column
              title="操作"
              key="action"
              width={360}
              align="center"
              render={(text, row) => (
                <span>
                  {this.renderEditButton(row, "device:edit")}
                  <Divider type="vertical" />
                  {this.renderDeleteButton(row, "device:delete")}
                </span>
              )}
            />
          </Table>
          <br />
          {this.renderPagination()}
        </Card>
        <EditPositionForm
          currentRowData={this.state.currentRowData}
          wrappedComponentRef={(formRef) => (this.editFormRef = formRef)}
          visible={this.state.editModalVisible}
          confirmLoading={this.state.editModalLoading}
          onCancel={this.handleEditEntityCancel}
          onOk={this.handleEditEntityOk}
        />
      </div>
    );
  }
}
export default PositionSetting;
screen/.gitignore
@@ -14,6 +14,7 @@
# misc
package-lock.json
yarn.lock
# Editor directories and files
.idea
screen/src/App.vue
@@ -27,10 +27,6 @@
      this.$router.replace('/home');
      // this.$router.replace('/');
      return
    } else {
      this.$router.replace({
        path: this.$route.path,
      });
    }
  },
}
screen/src/assets/img/home/77Combined Shape@2x.png
screen/src/assets/img/home/89Combined Shape@2x.png
screen/src/assets/img/home/Group@2x.png
screen/src/assets/img/home/Rectangle 4@2x.png
screen/src/assets/img/home/Shape@2x99.png
screen/src/components/column.js
File was deleted
screen/src/components/customDialog.vue
New file
@@ -0,0 +1,61 @@
<template>
  <div>
    <el-dialog v-bind="$attrs" v-on="$listeners">
      <slot></slot>
    </el-dialog>
  </div>
</template>
<script>
export default {
  components: {},
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  methods: {},
};
</script>
<style scoped lang="less">
::v-deep .el-dialog {
  background-image: url("../assets/img/home/Rectangle 4@2x.png");
  background-size: 100% 100%;
  .el-dialog__header {
    background-image: url("../assets/img/home/Group@2x.png");
    background-size: 100% 100%;
    padding: 30px 0 26px 0;
    text-align: center;
    position: relative;
    .el-dialog__title {
      font-size: 24px;
      color: #ffffff;
      letter-spacing: 1px;
      font-family: "Source Han Sans CN Bold";
    }
    .el-dialog__headerbtn {
      position: absolute;
      right: 30px;
      top: 30px;
      background-image: url("../assets/img/home/Shape@2x99.png");
      background-size: 100% 100%;
      width: 20px;
      height: 20px;
      i {
        display: none;
      }
    }
  }
  .el-dialog__body{
    padding: 20px 30px;
  }
}
</style>
screen/src/components/customPagination.vue
New file
@@ -0,0 +1,130 @@
<template>
  <div>
    <el-pagination
      v-bind="$attrs"
      v-on="$listeners"
      class="mt--16 txt-right"
      layout="total, sizes, prev, pager, next, jumper"
    >
    </el-pagination>
  </div>
</template>
<script>
export default {
  components: {},
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  methods: {},
};
</script>
<style scoped lang="less">
::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);
      }
    }
  }
}
</style>
screen/src/components/customPreview.vue
New file
@@ -0,0 +1,44 @@
<template>
  <div>
    <CustomDialog title="图片预览" :visible.sync="visible" width="1420px" @close="$emit('close')">
      <div style="height: 691px">
        <div v-for="(item, index) in imgArr" :key="index">
          <img :src="item" style="width: 100%; height: 100%" />
        </div>
      </div>
    </CustomDialog>
  </div>
</template>
<script>
export default {
  components: {},
  props: {
    show: {
      type: Boolean,
      default: false,
    },
    imgArr: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return { visible: false };
  },
  computed: {},
  watch: {
    show: {
      handler(newVal, oldVal) {
        this.visible = newVal;
      },
      immediate: true,
    },
  },
  created() {},
  mounted() {},
  methods: {},
};
</script>
<style scoped>
</style>
screen/src/components/customTable.vue
New file
@@ -0,0 +1,78 @@
<template>
  <div>
    <el-table
      v-bind="$attrs"
      v-on="$listeners"
      :row-class-name="getClassName"
      :header-row-class-name="'headClassName'"
    >
      <slot></slot>
    </el-table>
  </div>
</template>
<script>
export default {
  components: {},
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  methods: {
    getClassName({ row, rowIndex }) {
      if (rowIndex % 2 === 0) {
        return "oneRow";
      } else {
        return "twoRow";
      }
    },
  },
};
</script>
<style scoped lang="less">
::v-deep .el-table {
  background: transparent;
  &::before {
    background-color: transparent;
  }
  .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: rgba(14, 95, 255, .2) !important;
    height: 50px;
  }
}
</style>
screen/src/components/service.js
File was deleted
screen/src/components/tableModel.vue
File was deleted
screen/src/main.js
@@ -13,8 +13,18 @@
import 'echarts-gl';
import * as echarts from 'echarts';
import TitleBox from './components/titleBox.vue'
import CustomTable from './components/customTable.vue'
import CustomPagination from './components/customPagination.vue'
import CustomDialog from './components/customDialog.vue'
import CustomPreview from './components/customPreview.vue'
Vue.component('TitleBox', TitleBox)
Vue.component('CustomTable', CustomTable)
Vue.component('CustomPagination', CustomPagination)
Vue.component('CustomDialog', CustomDialog)
Vue.component('CustomPreview', CustomPreview)
Vue.prototype.$axios = axios
Vue.prototype.$echarts = echarts
screen/src/router/index.js
@@ -27,6 +27,48 @@
    }
  },
  {
    path: '/equipmentList',
    component: () => import('../view/equipmentList/index.vue'),
    meta: {
      title: '设备列表'
    }
  },
  {
    path: '/hiddenDanger',
    component: () => import('../view/hiddenDanger/index.vue'),
    meta: {
      title: '重大隐患列表'
    }
  },
  {
    path: '/workList',
    component: () => import('../view/workList/index.vue'),
    meta: {
      title: '工作内容管理'
    }
  },
  {
    path: '/workList/detail',
    component: () => import('../view/workList/detail.vue'),
    meta: {
      title: '工作内容详情'
    }
  },
  {
    path: '/accidentCase',
    component: () => import('../view/accidentCase/index.vue'),
    meta: {
      title: '事故案例'
    }
  },
   {
    path: '/accidentCase/detail',
    component: () => import('../view/accidentCase/detail.vue'),
    meta: {
      title: '事故案例详情'
    }
  },
  {
    path: '/projectHome',
    component: () => import('../view/projectHome/index.vue'),
    meta: {
screen/src/view/accidentCase/detail.vue
New file
@@ -0,0 +1,100 @@
<template>
  <div>
    <HeaderBox />
    <div class="pt--35 px--20 pb--54">
      <!-- 返回 -->
      <div>
        <img
          @click="backFun"
          src="../../assets/img/back.png"
          class="w--22 h--20 shrink0 mr--13 cursor-pointer"
        />
      </div>
      <div class="bgcolor1 mt--25 oa" style="height: 900px">
        <div class="flex a-center">
          <div class="fs--30 lh--30 c-fff SHSBold mr--8">
            德国模德机床中国总部及研发生产基地项目落户成都东部新区
          </div>
          <div class="typeBox">塔吊倒塌</div>
        </div>
        <div class="flex a-center j-between mt--24">
          <div class="flex a-center">
            <img
              src="../../assets/img/home/Shape@2x (1).png"
              class="mr--6 w--9 h--10"
            />
            <div class="SHSN fs--12 lh--12 c-fff">伤亡:造成 1 人死亡</div>
          </div>
          <div class="flex a-center">
            <img
              src="../../assets/img/home/Shape@2x (2).png"
              class="mr--6 w--8 h--10"
            />
            <div class="SHSN fs--12 lh--12 c-fff">河北省秦皇岛市昌黎县</div>
          </div>
          <div class="flex a-center">
            <img
              src="../../assets/img/home/Shape@2x (3).png"
              class="mr--6 w--10 h--9"
            />
            <div class="SHSN fs--12 lh--12 c-fff">2025年11月10日</div>
          </div>
        </div>
        <div class="mt--18 fs--14 c-fff SHSN">
          德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区
        </div>
        <div class="mt--26 flex flex-column a-center gap--18">
          <img
            style="width: 730px; height: 348px"
            src="../../assets/img/home/Shape@2x (3).png"
          />
          <img
            style="width: 730px; height: 348px"
            src="../../assets/img/home/Shape@2x (3).png"
          />
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import HeaderBox from "../header/index.vue";
import moment from "moment";
export default {
  components: { HeaderBox },
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  methods: {
    backFun() {
      this.$router.go(-1);
    },
  },
};
</script>
<style scoped lang="less">
.typeBox {
  min-width: 60px;
  line-height: 20px;
  text-align: center;
  background: linear-gradient(180deg, #ff4d4f 0%, #e5484d 100%);
  border-radius: 20px;
  border: 1px solid #e5484d;
  font-size: 12px;
  color: #ffffff;
  font-family: "Source Han Sans CN Bold";
}
.bgcolor1 {
  background: rgba(47, 85, 143, 0.3);
  border: 2px solid #3d7fff;
  padding: 45px 50px;
  height: 100%;
}
</style>
screen/src/view/accidentCase/index.vue
New file
@@ -0,0 +1,351 @@
<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 w--300 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 w--300 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 w--300 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 w--300 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 w--300 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 SHSR">搜索</div>
        </div>
      </div>
      <!-- 表格 -->
      <div class="mt--20 border1 oa" style="height: 800px">
        <div
          v-for="(item, index) in 10"
          :key="item"
          class="flex a-center j-between px--32 py--20 c-fff cursor-pointer tableItem"
          :class="{ bgcolor2: (index + 1) % 2 != 0 }"
          @click="toDetail(item)"
        >
          <div class="flex a-center">
            <div class="fs--29 lh--29 SHSN">31</div>
            <div class="border2 ml--15 mr--16"></div>
            <div class="fs--12 lh--14 SHSN color1">
              <p>2025</p>
              <p>12</p>
            </div>
          </div>
          <div class="ml--79 flex1">
            <div class="fs--20 lh--20 SHSBold mt--2">
              秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢
            </div>
            <div class="flex a-center j-between mt--6">
              <div class="flex a-center gap--7">
                <img
                  src="../../assets/img/home/Shape@2x (2).png"
                  class="shrink0 w--8 h--9"
                />
                <div class="fs--12 lh--12 c-fff SHSN">河北省秦皇岛市昌黎县</div>
              </div>
              <div class="typeBox">塔吊倒塌</div>
            </div>
            <div class="mt--5 fs--14 lh--20 SHSR c-fff">
              秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故
            </div>
          </div>
          <img
            src="../../assets/img/logo.png"
            class="w--264 h--160 shrink0 ml--54 br--10"
          />
        </div>
      </div>
      <CustomPagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[100, 200, 300, 400]"
        :page-size="10"
        :total="400"
      />
    </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: {
    toDetail(item) {
      this.$router.push({
        path: "/accidentCase/detail",
        query: {
          id: item.id,
        },
      });
    },
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
    },
    handleClick(type) {
      this.$refs[`datetime${type}`].focus();
    },
    backFun() {
      this.$router.go(-1);
    },
  },
};
</script>
<style scoped lang="less">
.tableItem:hover {
  background-color: rgba(17, 40, 255, 0.2) !important;
}
.typeBox {
  min-width: 60px;
  line-height: 20px;
  text-align: center;
  background: linear-gradient(180deg, #ff4d4f 0%, #e5484d 100%);
  border-radius: 20px;
  border: 1px solid #e5484d;
  font-size: 12px;
  color: #ffffff;
  font-family: "Source Han Sans CN Bold";
}
.border1 {
  border: 2px solid rgba(61, 127, 255, 0.3);
}
.border2 {
  border: 1px solid #ffffff;
  transform: rotate(20deg);
  height: 21px;
}
.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(14, 95, 255, 0.2);
}
.color1 {
  color: rgba(255, 255, 255, 0.8);
}
.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;
    padding: 0 26px;
    border: 1px solid #307ad9;
    box-sizing: border-box;
    cursor: pointer;
  }
}
.btnColor {
  color: #00ebfc;
}
::v-deep .el-descriptions {
  .el-descriptions__body {
    background-color: transparent;
    .el-descriptions-item__container {
      color: #ffffff;
      font-family: "Source Han Sans CN Regular";
    }
  }
}
</style>
screen/src/view/equipmentList/index.vue
New file
@@ -0,0 +1,490 @@
<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 w--300 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 w--300 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 w--300 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 w--300 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 w--300 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 SHSR">搜索</div>
        </div>
      </div>
      <!-- 表格 -->
      <CustomTable
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        height="800"
        style="border: 2px solid #3d7fff"
      >
        <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="使用单位" prop="projectName" />
        <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="本月检查情况" prop="projectName">
          <template #default="{ row, $index }">
            <div class="flex a-center j-center">
              <div class="ripple">
                <div
                  class="ripple-wave wave-1"
                  :class="{ bgColor3: $index === 0 }"
                ></div>
                <div
                  class="ripple-wave wave-2"
                  :class="{ bgColor4: $index === 0 }"
                ></div>
                <div
                  class="ripple-wave wave-3"
                  :class="{ bgColor5: $index === 0 }"
                ></div>
              </div>
              <div class="ml--6 SHSR">{{ $index }}</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="最近一次检查时间" prop="projectName" />
        <el-table-column label="操作">
          <template #default="{ row }">
            <el-button
              @click="toHiddenDanger(row, 3)"
              type="text"
              class="btnColor"
              >隐患</el-button
            >
            <el-button
              type="text"
              class="btnColor"
              @click="projectVisible = true"
              >详情</el-button
            >
          </template>
        </el-table-column>
      </CustomTable>
      <CustomPagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[100, 200, 300, 400]"
        :page-size="10"
        :total="400"
      />
    </div>
    <!-- 项目列表弹窗 -->
    <CustomDialog title="项目" :visible.sync="projectVisible" width="1420px">
      <CustomTable
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        height="630"
      >
        <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="风险类型" prop="projectName" />
        <el-table-column label="操作">
          <template #default="{ row }">
            <el-popover trigger="click" popper-class="custom-popper">
              <template #reference>
                <el-button type="text" class="btnColor">查看报告</el-button>
              </template>
              <div
                class="h100 flex flex-column a-center j-between c-fff fs--16 SHSBold"
              >
                <div
                  @click="openReport('safe')"
                  class="py--12 w100 txt-center br--10 bgcolor6 cursor-pointer"
                >
                  综合报告
                </div>
                <div
                  @click="openReport('device')"
                  class="py--12 w100 txt-center br--10 bgcolor7 cursor-pointer"
                >
                  设备报告
                </div>
              </div>
            </el-popover>
          </template>
        </el-table-column>
      </CustomTable>
    </CustomDialog>
    <!-- 检查报告弹窗 -->
    <CustomDialog title="检查报告" :visible.sync="reportVisible" width="1420px">
      <div style="height: 691px" class="oa">
        <iframe
          v-if="reportUrl"
          :src="reportUrl"
          width="100%"
          height="100%"
          frameborder="0"
        ></iframe>
      </div>
    </CustomDialog>
  </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,
      projectVisible: false,
      reportVisible: false,
      reportUrl: "",
      safeReportUrl:
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
      deviceReportUrl:
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    };
  },
  computed: {},
  watch: {
    dateTime: {
      handler(newVal, oldVal) {
        if (newVal) {
          this.dateTxt = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss");
        }
      },
      immediate: true,
    },
  },
  created() {},
  mounted() {},
  methods: {
    toHiddenDanger(row, type) {
      this.$router.push({
        path: "/hiddenDanger",
        query: {
          projectId: row.projectId,
          activeTab: type,
        },
      });
    },
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
    },
    handleClick(type) {
      this.$refs[`datetime${type}`].focus();
    },
    backFun() {
      this.$router.go(-1);
    },
    openReport(type) {
      if (type === "safe") {
        this.reportUrl = this.safeReportUrl;
      } else if (type === "device") {
        this.reportUrl = this.deviceReportUrl;
      } else {
        this.reportUrl = "";
      }
      this.reportVisible = !!this.reportUrl;
    },
  },
};
</script>
<style lang="less">
.custom-popper {
  background: transparent;
  background-image: url("../../assets/img/home/77Combined Shape@2x.png");
  background-size: 100% 100%;
  padding: 31px 38px;
  border-radius: 0px;
  border: none;
  box-shadow: none;
  width: 227px;
  height: 180px;
  .popper__arrow {
    display: none;
  }
}
</style>
<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);
}
.bgColor3 {
  background: rgba(67, 221, 189, 1) !important;
}
.bgColor4 {
  background: rgba(67, 221, 189, 0.6) !important;
}
.bgColor5 {
  background: rgba(67, 221, 189, 0.4) !important;
}
.bgcolor6 {
  background: linear-gradient(270deg, #64aef0 0%, #4b70ec 100%);
}
.bgcolor7 {
  background: linear-gradient(270deg, #3dabea 0%, #28a5ec 100%);
}
.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;
    padding: 0 26px;
    border: 1px solid #307ad9;
    box-sizing: border-box;
    cursor: pointer;
  }
}
.btnColor {
  color: #00ebfc;
}
::v-deep .el-descriptions {
  .el-descriptions__body {
    background-color: transparent;
    .el-descriptions-item__container {
      color: #ffffff;
      font-family: "Source Han Sans CN Regular";
    }
  }
}
.ripple {
  position: relative;
  width: 14px;
  height: 14px;
}
.ripple-wave {
  position: absolute;
  border-radius: 50%;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.wave-1 {
  width: 14px;
  height: 14px;
  background-color: rgba(255, 55, 95, 1);
}
.wave-2 {
  width: 20px;
  height: 20px;
  background-color: rgba(255, 55, 95, 0.6);
  animation: ripple-effect 2s ease-out infinite;
}
.wave-3 {
  width: 24px;
  height: 24px;
  background-color: rgba(255, 55, 95, 0.4);
  animation: ripple-effect 2s ease-out infinite 1s;
}
@keyframes ripple-effect {
  0% {
    transform: translate(-50%, -50%) scale(0.7);
    opacity: 0;
  }
  20% {
    opacity: 1;
    opacity: 1;
  }
  100% {
    -webkit-transform: translate(-50%, -50%) scale(1.4);
    opacity: 0;
  }
}
</style>
screen/src/view/hiddenDanger/index.vue
New file
@@ -0,0 +1,669 @@
<template>
  <div class="relative">
    <HeaderBox />
    <div class="pt--35 px--20 pb--54">
      <!-- 返回 -->
      <div>
        <img
          @click="backFun"
          src="../../assets/img/back.png"
          class="w--22 h--20 shrink0 mr--13 cursor-pointer"
        />
      </div>
      <!-- tab -->
      <div
        class="flex a-center absolute postion-center br--16 top--130 br--16 c-fff fs--14 bgcolor4 SSHR"
      >
        <div @click="activeTab = 1" class="lh--32 px--20 cursor-pointer z-10">
          重大隐患
        </div>
        <div @click="activeTab = 2" class="lh--32 px--20 cursor-pointer z-10">
          安全隐患
        </div>
        <div @click="activeTab = 3" class="lh--32 px--20 cursor-pointer z-10">
          设备隐患
        </div>
        <div class="activeBox" :style="{ left: (activeTab - 1) * 95 + 'px' }">
          占位盒子
        </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 w--300 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 w--300 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
          v-if="activeTab == 1"
          class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 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
          v-else
          class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 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 w--300 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 w--300 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 w--300 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 SHSR">搜索</div>
        </div>
      </div>
      <!-- 表格 -->
      <CustomTable
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        height="800"
        style="border: 2px solid #3d7fff"
      >
        <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="问题部位" prop="projectName" />
        <el-table-column label="问题备注" prop="projectName" />
        <el-table-column label="隐患等级" prop="projectName" />
        <el-table-column
          v-if="activeTab == 1"
          label="隐患类型"
          prop="projectName"
        />
        <el-table-column label="图片" prop="projectName">
          <template #default="{ row }"
            ><div
              class="btnColor cursor-pointer"
              :class="false && 'disableColor'"
              @click="previewVisible = true"
            >
              1张
            </div>
          </template>
        </el-table-column>
        <el-table-column label="检查时间" prop="projectName" />
        <el-table-column label="整改状态" prop="projectName">
          <template #default="{ row, $index }">
            <div class="flex a-center j-center">
              <div class="ripple">
                <div
                  class="ripple-wave wave-1"
                  :class="{ bgColor3: $index === 0 }"
                ></div>
                <div
                  class="ripple-wave wave-2"
                  :class="{ bgColor4: $index === 0 }"
                ></div>
                <div
                  class="ripple-wave wave-3"
                  :class="{ bgColor5: $index === 0 }"
                ></div>
              </div>
              <div class="ml--6 SHSR">{{ $index }}</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="责任人" prop="projectName" />
        <el-table-column label="操作">
          <template #default="{ row }">
            <el-button @click="updatePeople = true" type="text" class="btnColor"
              >编辑责任人</el-button
            >
            <el-button
              type="text"
              class="btnColor"
              @click="detailVisible = true"
              >详情</el-button
            >
          </template>
        </el-table-column>
      </CustomTable>
      <CustomPagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[100, 200, 300, 400]"
        :page-size="10"
        :total="400"
      />
    </div>
    <!-- 修改责任人 -->
    <CustomDialog title="责任人" :visible.sync="updatePeople" width="600px">
      <div class="pt--37 px--45 pb--64">
        <input
          v-model="peopleName"
          placeholder="请输入"
          class="w100 h--60 fs--14 SHSR py--23 px--21 bgcolor5 c-fff"
        />
        <div class="flex a-center j-center gap--30 mt--59 SHSR fs--16 c-fff">
          <div
            @click="closeUpdatePeople"
            class="w--150 lh--40 txt-center bgcolor2 br--4 cursor-pointer"
          >
            取消
          </div>
          <div
            @click="saveUpdatePeople"
            class="w--150 lh--40 txt-center bgcolor3 br--4 cursor-pointer"
          >
            保存
          </div>
        </div>
      </div>
    </CustomDialog>
    <!-- 隐患详情 -->
    <CustomDialog title="项目名称" :visible.sync="detailVisible" width="1420px">
      <el-tabs v-model="activeName" type="card" @tab-click="handleClickTab">
        <el-tab-pane label="基本信息" name="first">
          <div class="flex j-between gap--30 mt--30">
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">计划名称:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">项目名称:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
          </div>
          <div class="flex j-between gap--30 mt--30">
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">检查内容:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">责任人:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
          </div>
          <div class="flex j-between gap--30 mt--30">
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">问题部门:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">创建时间:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
          </div>
          <div class="mt--30">
            <div class="SHSR fs--16 lh--16 mb--17 color1">规范条款:</div>
            <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
              计划名称计划名称计划名称
            </div>
          </div>
          <div class="mt--30">
            <div class="SHSR fs--16 lh--16 mb--17 color1">建议措施:</div>
            <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
              计划名称计划名称计划名称
            </div>
          </div>
          <div class="flex j-between gap--30 mt--30">
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">问题数量:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">扣除积分:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
          </div>
          <div class="flex j-between gap--30 mt--30">
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">附加分数:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">备注:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
          </div>
        </el-tab-pane>
        <el-tab-pane label="复查记录(无)" name="second">
          <div class="flex j-between gap--30 mt--30">
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">复合内容:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">复合状态:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
          </div>
          <div class="flex j-between gap--30 mt--30">
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">复合图片:</div>
              <div
                class="lh--60 px--19 btnColor SHSBold fs--18 w100 cursor-pointer"
                :class="false && 'disableColor'"
                @click="previewVisible = true"
              >
                1张
              </div>
            </div>
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">复核人:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
          </div>
          <div class="flex j-between gap--30 mt--30">
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">创建时间:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
            <div class="flex1">
              <div class="SHSR fs--16 lh--16 mb--17 color1">更新时间:</div>
              <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor6">
                计划名称计划名称计划名称
              </div>
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </CustomDialog>
    <!-- 图片预览 -->
    <CustomPreview
      :show="previewVisible"
      :imgArr="[]"
      @close="previewVisible = false"
    />
  </div>
</template>
<script>
import HeaderBox from "../header/index.vue";
import moment from "moment";
export default {
  components: { HeaderBox },
  props: {},
  data() {
    return {
      activeTab: 1,
      dateTime: null,
      projectId: null,
      dateTxt: "",
      currentPage: 1,
      updatePeople: false,
      peopleName: "",
      detailVisible: false,
      activeName: "first",
      previewVisible: false,
    };
  },
  computed: {},
  watch: {
    dateTime: {
      handler(newVal, oldVal) {
        if (newVal) {
          this.dateTxt = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss");
        }
      },
      immediate: true,
    },
  },
  created() {
    if (this.$route.query.activeTab) {
      this.activeTab = this.$route.query.activeTab;
    }
  },
  mounted() {},
  methods: {
    handleClickTab(tab) {
      this.activeName = tab.name;
    },
    closeUpdatePeople() {
      this.updatePeople = false;
      this.peopleName = "";
    },
    saveUpdatePeople() {
      if (!this.peopleName) {
        this.$message({
          message: "请输入责任人",
          type: "warning",
        });
        return;
      }
      this.$message({
        message: "保存成功",
        type: "success",
      });
      this.closeUpdatePeople();
    },
    backFun() {
      this.$router.go(-1);
    },
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
    },
  },
};
</script>
<style scoped lang="less">
input::placeholder {
  color: rgba(255, 255, 255, 0.2);
}
input:focus {
  outline: none;
}
.btnColor {
  color: #00ebfc;
}
.disableColor {
  color: #ccc;
  cursor: not-allowed;
}
.color1 {
  color: rgba(255, 255, 255, 0.9);
}
.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: #838fbb;
}
.bgcolor3 {
  background: linear-gradient(270deg, #09b9ff 0%, #4d68ff 100%);
}
.bgcolor4 {
  background: #06175b;
  border-radius: 16px;
  border: 1px solid #204fb3;
}
.bgcolor5 {
  background: rgba(6, 23, 91, 0.6);
  border: 1px solid #204fb3;
}
.bgcolor6 {
  background: rgba(24, 83, 200, 0.2);
}
.activeBox {
  position: absolute;
  top: 0;
  left: 0;
  padding: 0 20px;
  height: 32px;
  background: #0600e4;
  color: transparent;
  box-shadow: inset 0px 0px 20px 0px rgba(102, 255, 255, 0.52);
  border-radius: 20px;
  border: 1px solid rgba(50, 197, 255, 0.22);
  transition: all 0.3s ease-in-out;
}
.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;
    padding: 0 26px;
    border: 1px solid #307ad9;
    box-sizing: border-box;
    cursor: pointer;
  }
}
::v-deep .el-tabs {
  .el-tabs__header {
    border-bottom: none;
    margin: 0;
    .el-tabs__nav {
      border: none;
      .el-tabs__item {
        border: none;
        color: rgba(255, 255, 255, 0.7);
        font-size: 14px;
        font-family: "Source Han Sans CN Regular";
        padding: 0 32px;
        height: 34px;
        line-height: 34px;
        &:hover {
          font-family: "Source Han Sans CN Bold";
          color: #ffffff;
          background: linear-gradient(180deg, #1f54ae 0%, #017be7 100%);
          border-radius: 6px 6px 0px 0px;
        }
      }
      .is-active {
        font-family: "Source Han Sans CN Bold";
        color: #ffffff;
        background: linear-gradient(180deg, #1f54ae 0%, #017be7 100%);
        border-radius: 6px 6px 0px 0px;
      }
    }
  }
}
</style>
screen/src/view/home/index.vue
@@ -22,7 +22,7 @@
        src="../../assets/img/home/Group@2x (4).png"
        class="w--110 h--110 mr--9 shrink0"
      />
      <div class="bgimg4 pt--10 c-fff">
      <div @click="toHiddenDanger" class="bgimg4 pt--10 c-fff cursor-pointer">
        <div class="flex a-center ml--14">
          <div class="ripple">
            <div class="ripple-wave wave-1"></div>
@@ -207,7 +207,10 @@
          <template #title> 设备数据总览 </template>
          <template #content>
            <div class="flex j-end mt--8">
              <div class="flex a-center pl--11 pr--13 py--6 bgimg2">
              <div
                @click="toEquipmentList"
                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>
@@ -249,6 +252,7 @@
          <template #title> 事故简讯 </template>
          <template #right>
            <div
              @click="toAccidentCaseList"
              class="flex a-center py--6 pl--10 pr--8 br--4 bgcolor5 cursor-pointer"
            >
              <div class="fs--12 lh--12 c-fff mr--4 SHSR">详情</div>
@@ -269,6 +273,7 @@
            >
              <div>
                <div
                  @click="toAccidentCaseDetail(item)"
                  v-for="(item, index) in scrollData"
                  :key="`${item.id}-${index}`"
                  :class="(index + 1) % 2 === 0 ? 'bgcolor7' : ''"
@@ -321,6 +326,7 @@
          <template #title> 工作展示 </template>
          <template #right>
            <div
              @click="toWorkList"
              class="flex a-center py--6 pl--10 pr--8 br--4 bgcolor5 cursor-pointer"
            >
              <div class="fs--12 lh--12 c-fff mr--4 SHSR">详情</div>
@@ -341,7 +347,7 @@
                @change="handleChangeCarousel"
              >
                <el-carousel-item v-for="(item, index) in 4" :key="index">
                  <div>
                  <div @click="toWorkDetail(item)" class="cursor-pointer">
                    <img
                      src="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/1bcd9db5-c909-4edc-a3d2-61cc33c54462.jpg"
                      class="w100 h--290"
@@ -438,10 +444,36 @@
    this.stopAutoScroll();
  },
  methods: {
    toPorjectList() {
      this.$router.replace({
        path: "/projectList",
    toAccidentCaseDetail(item) {
      this.$router.push({
        path: "/accidentCase/detail",
        query: {
          id: item.id,
        },
      });
    },
    toAccidentCaseList() {
      this.$router.push("/accidentCase");
    },
    toWorkDetail(item) {
      this.$router.push({
        path: "/workList/detail",
        query: {
          id: item.id,
        },
      });
    },
    toWorkList() {
      this.$router.push("/workList");
    },
    toPorjectList() {
      this.$router.push("/projectList");
    },
    toEquipmentList() {
      this.$router.push("/equipmentList");
    },
    toHiddenDanger() {
      this.$router.push("/hiddenDanger");
    },
    // 切换活动索引
    changeActiveIndex(index) {
@@ -823,7 +855,7 @@
}
.activeBox2 {
  left: 100px;
  left: 95px;
}
.leftBox {
screen/src/view/projectList/index.vue
@@ -13,7 +13,7 @@
      <!-- 搜索 -->
      <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"
          class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 bgcolor1 searchBox"
        >
          <el-select
            filterable
@@ -35,7 +35,7 @@
          />
        </div>
        <div
          class="flex a-center j-between pl--18 pr--15 h--40 relative flex1 bgcolor1 searchBox"
          class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 bgcolor1 searchBox"
        >
          <el-select
            filterable
@@ -57,7 +57,7 @@
          />
        </div>
        <div
          class="flex a-center j-between pl--18 pr--15 h--40 relative flex1 bgcolor1 searchBox"
          class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 bgcolor1 searchBox"
        >
          <el-select
            filterable
@@ -80,7 +80,7 @@
        </div>
        <div
          @click="handleClick(1)"
          class="flex a-center j-between px--20 flex1 h--40 relative bgcolor1 picker"
          class="flex a-center j-between px--20 w--300 h--40 relative bgcolor1 picker"
        >
          <el-date-picker
            v-model="dateTime"
@@ -109,7 +109,7 @@
        </div>
        <div
          @click="handleClick(2)"
          class="flex a-center j-between px--20 flex1 h--40 relative bgcolor1 picker"
          class="flex a-center j-between px--20 w--300 h--40 relative bgcolor1 picker"
        >
          <el-date-picker
            v-model="dateTime"
@@ -137,7 +137,7 @@
          />
        </div>
        <div
          class="flex a-center j-between flex1 pl--20 h--40 relative bgcolor1 searchBox"
          class="flex a-center j-between w--300 pl--20 h--40 relative bgcolor1 searchBox"
        >
          <el-select
            filterable
@@ -157,17 +157,16 @@
        </div>
      </div>
      <!-- 表格 -->
      <el-table
      <CustomTable
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        height="800"
        :row-class-name="getClassName"
        :header-row-class-name="'headClassName'"
        style="border: 2px solid #3d7fff"
      >
        <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">
          <template #default="{ row }">
            <div class="flex j-center" @click="companyVisible = true">
              <div
                class="w--70 lh--30 txt-center j-center bgColor2 SHSR cursor-pointer"
              >
@@ -180,37 +179,123 @@
        <el-table-column label="本月检查情况" prop="projectName" />
        <el-table-column label="最后一次检查时间" prop="projectName" />
        <el-table-column label="本月检查风险" prop="projectName">
          <template #default="scope">
          <template #default="{ row, $index }">
            <div class="flex a-center j-center">
              <div class="ripple">
                <div class="ripple-wave wave-1"></div>
                <div class="ripple-wave wave-2"></div>
                <div class="ripple-wave wave-3"></div>
                <div
                  class="ripple-wave wave-1"
                  :class="{ bgColor3: $index === 0 }"
                ></div>
                <div
                  class="ripple-wave wave-2"
                  :class="{ bgColor4: $index === 0 }"
                ></div>
                <div
                  class="ripple-wave wave-3"
                  :class="{ bgColor5: $index === 0 }"
                ></div>
              </div>
              <div class="ml--6 SHSR">已检查</div>
              <div class="ml--6 SHSR">{{ $index }}</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template #default="scope">
          <template #default="{ row }">
            <el-button type="text" class="btnColor">详情</el-button>
            <el-button type="text" class="btnColor">隐患</el-button>
            <el-button type="text" class="btnColor">报告</el-button>
            <el-button
              @click="toHiddenDanger(row, 2)"
              type="text"
              class="btnColor"
              >隐患</el-button
            >
            <el-button
              type="text"
              class="btnColor"
              @click="projectVisible = true"
              >报告</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        class="mt--16 txt-right"
      </CustomTable>
      <CustomPagination
        @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>
    <!-- 项目列表弹窗 -->
    <CustomDialog title="项目" :visible.sync="projectVisible" width="1420px">
      <CustomTable
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        height="630"
      >
        <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="风险类型" prop="projectName" />
        <el-table-column label="操作">
          <template #default="{ row }">
            <el-popover trigger="click" popper-class="custom-popper">
              <template #reference>
                <el-button type="text" class="btnColor">查看报告</el-button>
              </template>
              <div
                class="h100 flex flex-column a-center j-between c-fff fs--16 SHSBold"
              >
                <div
                  @click="openReport('safe')"
                  class="py--12 w100 txt-center br--10 bgcolor6 cursor-pointer"
                >
                  安全报告
                </div>
                <div
                  @click="openReport('device')"
                  class="py--12 w100 txt-center br--10 bgcolor7 cursor-pointer"
                >
                  设备报告
                </div>
              </div>
            </el-popover>
          </template>
        </el-table-column>
      </CustomTable>
    </CustomDialog>
    <!-- 单位信息弹窗 -->
    <CustomDialog title="单位信息" :visible.sync="companyVisible" width="1420px">
      <el-descriptions>
        <el-descriptions-item label="施工单位">成都喜望</el-descriptions-item>
        <el-descriptions-item label="项目经理">张三</el-descriptions-item>
        <el-descriptions-item label="联系方式"
          >18100000000</el-descriptions-item
        >
        <el-descriptions-item label="监理单位">成都喜望</el-descriptions-item>
        <el-descriptions-item label="总监">张三</el-descriptions-item>
        <el-descriptions-item label="联系方式"
          >18100000000</el-descriptions-item
        >
        <el-descriptions-item label="建设单位">成都喜望</el-descriptions-item>
        <el-descriptions-item label="项目负责人">张三</el-descriptions-item>
        <el-descriptions-item label="联系方式"
          >18100000000</el-descriptions-item
        >
      </el-descriptions>
    </CustomDialog>
    <!-- 检查报告弹窗 -->
    <CustomDialog title="检查报告" :visible.sync="reportVisible" width="1420px">
      <div style="height: 691px" class="oa">
        <iframe
          v-if="reportUrl"
          :src="reportUrl"
          width="100%"
          height="100%"
          frameborder="0"
        ></iframe>
      </div>
    </CustomDialog>
  </div>
</template>
@@ -226,6 +311,14 @@
      projectId: null,
      dateTxt: "",
      currentPage: 1,
      projectVisible: false,
      companyVisible: false,
      reportVisible: false,
      reportUrl: "",
      safeReportUrl:
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
      deviceReportUrl:
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    };
  },
  computed: {},
@@ -242,6 +335,16 @@
  created() {},
  mounted() {},
  methods: {
    toHiddenDanger(row,type) {
      this.$router.push({
        path: '/hiddenDanger',
        query: {
          projectId: row.projectId,
          activeTab: type,
        }
      })
    },
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
    },
@@ -255,21 +358,38 @@
    },
    backFun() {
      this.$router.replace({
        path: "/home",
      });
      this.$router.go(-1);
    },
    getClassName({ row, rowIndex }) {
      if (rowIndex % 2 === 0) {
        return "oneRow";
    openReport(type) {
      if (type === "safe") {
        this.reportUrl = this.safeReportUrl;
      } else if (type === "device") {
        this.reportUrl = this.deviceReportUrl;
      } else {
        return "twoRow";
        this.reportUrl = "";
      }
      this.reportVisible = !!this.reportUrl;
    },
  },
};
</script>
<style lang="less">
.custom-popper {
  background: transparent;
  background-image: url("../../assets/img/home/77Combined Shape@2x.png");
  background-size: 100% 100%;
  padding: 31px 38px;
  border-radius: 0px;
  border: none;
  box-shadow: none;
  width: 227px;
  height: 180px;
  .popper__arrow {
    display: none;
  }
}
</style>
<style scoped lang="less">
.bgcolor1 {
  background: rgba(2, 0, 77, 0.8);
@@ -293,46 +413,12 @@
  background: rgba(67, 221, 189, 0.4) !important;
}
::v-deep .el-table {
  &::before {
    background-color: transparent;
  }
  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;
  }
.bgcolor6 {
  background: linear-gradient(270deg, #64aef0 0%, #4b70ec 100%);
}
.bgcolor7 {
  background: linear-gradient(270deg, #3dabea 0%, #28a5ec 100%);
}
.picker {
@@ -387,111 +473,19 @@
  }
}
::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;
}
::v-deep .el-descriptions {
  .el-descriptions__body {
    background-color: transparent;
    .el-descriptions-item__container {
      color: #ffffff;
      font-family: "Source Han Sans CN Regular";
    }
  }
}
.ripple {
@@ -542,4 +536,4 @@
    opacity: 0;
  }
}
</style>
</style>
screen/src/view/workList/detail.vue
New file
@@ -0,0 +1,79 @@
<template>
  <div>
    <HeaderBox />
    <div class="pt--35 px--20 pb--54">
      <!-- 返回 -->
      <div>
        <img
          @click="backFun"
          src="../../assets/img/back.png"
          class="w--22 h--20 shrink0 mr--13 cursor-pointer"
        />
      </div>
      <div class="bgcolor1 mt--25 oa" style="height: 900px;">
        <div class="fs--30 lh--30 c-fff SHSBold">
          德国模德机床中国总部及研发生产基地项目落户成都东部新区
        </div>
        <div class="flex a-center gap--20 mt--24">
          <div class="flex a-center">
            <img
              src="../../assets/img/home/Shape@2x (3).png"
              class="mr--6 w--10 h--9"
            />
            <div class="SHSN fs--12 lh--12 c-fff">2025年11月10日</div>
          </div>
          <div class="lh--20 px--8 br--10 fs--12 bgcolor2 c-fff SHSBold">
            工作视察
          </div>
        </div>
        <div class="mt--18 fs--14 c-fff SHSN">
          德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区德国模德机床中国总部及研发生产基地项目落户成都东部新区
        </div>
        <div class="mt--26 flex flex-column a-center gap--18">
          <img
            style="width: 730px;height: 348px;"
            src="../../assets/img/home/Shape@2x (3).png"
          />
          <img
            style="width: 730px;height: 348px;"
            src="../../assets/img/home/Shape@2x (3).png"
          />
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import HeaderBox from "../header/index.vue";
import moment from "moment";
export default {
  components: { HeaderBox },
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  methods: {
    backFun() {
      this.$router.go(-1);
    },
  },
};
</script>
<style scoped lang="less">
.bgcolor1 {
  background: rgba(47, 85, 143, 0.3);
  border: 2px solid #3d7fff;
  padding: 45px 50px;
  height: 100%;
}
.bgcolor2 {
  background: #09b9ff;
  border: 1px solid #017be7;
}
</style>
screen/src/view/workList/index.vue
New file
@@ -0,0 +1,533 @@
<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 j-between mt--24 mb--20">
        <div class="flex a-center gap--16">
          <div
            class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 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 w--300 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 w--300 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 w--300 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 SHSR">搜索</div>
          </div>
        </div>
        <div
          @click="formVisible = true"
          class="flex a-center j-center w--150 h--40 cursor-pointer br--4 bgcolor8"
        >
          <img
            src="../../assets/img/home/89Combined Shape@2x.png"
            class="w--12 h--12 shrink0 mr--10"
          />
          <div class="fs--14 lh--14 c-fff SHSR">新增</div>
        </div>
      </div>
      <!-- 表格 -->
      <CustomTable
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        height="800"
        style="border: 2px solid #3d7fff"
      >
        <el-table-column label="编号" prop="projectName">
          <template #default="{ row, $index }">
            {{ $index + 1 }}
          </template>
        </el-table-column>
        <el-table-column label="标题" prop="projectName" />
        <el-table-column label="简介" prop="projectName" />
        <el-table-column label="图片" prop="projectName">
          <template #default="{ row }"
            ><div
              class="btnColor cursor-pointer"
              :class="false && 'disableColor'"
              @click="previewVisible = true"
            >
              1张
            </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="操作">
          <template #default="{ row }">
            <el-button type="text" class="btnColor" @click="toDetail(row)"
              >详情</el-button
            >
            <el-button type="text" class="btnColor" @click="editForm(row)">编辑</el-button>
            <el-button type="text" class="btnColor">删除</el-button>
            <el-button type="text" class="btnColor">隐藏</el-button>
          </template>
        </el-table-column>
      </CustomTable>
      <CustomPagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[100, 200, 300, 400]"
        :page-size="10"
        :total="400"
      />
    </div>
    <!-- 图片预览 -->
    <CustomPreview
      :show="previewVisible"
      :imgArr="[]"
      @close="previewVisible = false"
    />
    <!-- 新增/编辑 -->
    <CustomDialog
      title="新增工作内容"
      :visible.sync="formVisible"
      width="800px"
      @close="closeForm"
    >
      <div class="pt--30 px--45">
        <div>
          <div class="SHSR fs--16 lh--16 mb--17 color1">工作标题:</div>
          <input
            v-model="peopleName"
            placeholder="请输入"
            class="w100 h--60 fs--14 SHSR py--23 px--21 bgcolor5 c-fff"
          />
        </div>
        <div class="mt--30">
          <div class="SHSR fs--16 lh--16 mb--17 color1">工作类型:</div>
          <div
            class="flex a-center j-between w100 pl--18 pr--15 h--60 SHSR fs--14 c-fff bgcolor5 searchBox"
          >
            <el-select
              filterable
              v-model="projectId"
              placeholder="请选择工作类型"
              class="formSelect 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>
        <div class="mt--30">
          <div class="SHSR fs--16 lh--16 mb--17 color1">工作简介:</div>
          <textarea
            v-model="peopleName"
            placeholder="请输入"
            class="w100 h--120 fs--14 SHSR py--23 px--21 bgcolor5 c-fff"
          />
        </div>
        <div class="mt--30">
          <div class="SHSR fs--16 lh--16 mb--17 color1">工作图片:</div>
          <div class="flex gap--10">
            <el-image
              v-for="(item, index) in fileList"
              :key="index"
              :src="item.url"
              class="w--100 h--100 fileListBox"
              :preview-src-list="[item.url]"
            />
            <el-upload
              action="https://jsonplaceholder.typicode.com/posts/"
              :before-upload="beforeUpload"
              :limit="5"
              accept="image/png, image/jpeg, image/gif"
              :show-file-list="false"
              :on-success="handleSuccess"
            >
              <div
                class="flex a-center flex-column gap--15 px--20 py--20 border1 br--8 uploadBox"
              >
                <img
                  src="../../assets/img/home/89Combined Shape@2x.png"
                  class="w--18 h--18"
                />
                <div class="c-fff fs--16">上传图片</div>
              </div>
            </el-upload>
          </div>
          <div class="color1 mt--10 fs--16 SHSR">
            请上传<span class="btnColor">png、jpg、gif</span>格式图片
          </div>
        </div>
        <div class="flex a-center j-center gap--30 mt--59 SHSR fs--16 c-fff">
          <div
            @click="closeForm"
            class="w--150 lh--40 txt-center bgcolor2 br--4 cursor-pointer"
          >
            取消
          </div>
          <div
            @click="saveForm"
            class="w--150 lh--40 txt-center bgcolor3 br--4 cursor-pointer"
          >
            保存
          </div>
        </div>
      </div>
    </CustomDialog>
  </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,
      previewVisible: false,
      formVisible: false,
      peopleName: "",
      fileList: [],
    };
  },
  computed: {},
  watch: {
    dateTime: {
      handler(newVal, oldVal) {
        if (newVal) {
          this.dateTxt = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss");
        }
      },
      immediate: true,
    },
  },
  created() {},
  mounted() {},
  methods: {
    handleSuccess(response, file, fileList) {
      console.log(response, file, fileList);
      this.fileList = fileList;
      this.$message.success("上传成功");
    },
    beforeUpload(file) {
      const isJPG = file.type === "image/jpeg";
      const isPNG = file.type === "image/png";
      const isGIF = file.type === "image/gif";
      if (!isJPG && !isPNG && !isGIF) {
        this.$message.error("上传图片格式必须为jpg、png、gif");
        return false;
      }
      return true;
    },
    editForm(row) {
      this.formVisible = true;
    },
    closeForm() {
      this.formVisible = false;
    },
    saveForm() {
      this.closeForm();
    },
    toDetail(row) {
      this.$router.push({
        path: "/workList/detail",
        query: {
          projectId: row.projectId,
        },
      });
    },
    toHiddenDanger(row, type) {
      this.$router.push({
        path: "/hiddenDanger",
        query: {
          projectId: row.projectId,
          activeTab: type,
        },
      });
    },
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
    },
    handleClick(type) {
      this.$refs[`datetime${type}`].focus();
    },
    backFun() {
      this.$router.go(-1);
    },
  },
};
</script>
<style scoped lang="less">
.border1 {
  border: 2px dashed #8c939d;
}
input::placeholder {
  color: rgba(255, 255, 255, 0.2);
}
input:focus {
  outline: none;
}
textarea::placeholder {
  color: rgba(255, 255, 255, 0.2);
}
textarea:focus {
  outline: none;
}
.uploadBox:hover {
  border-color: #00ebfc !important;
}
.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);
}
.bgColor3 {
  background: rgba(67, 221, 189, 1) !important;
}
.bgColor4 {
  background: rgba(67, 221, 189, 0.6) !important;
}
.bgColor5 {
  background: rgba(67, 221, 189, 0.4) !important;
}
.bgcolor2 {
  background: #838fbb;
}
.bgcolor3 {
  background: linear-gradient(270deg, #09b9ff 0%, #4d68ff 100%);
}
.bgcolor5 {
  background: rgba(6, 23, 91, 0.6);
  border: 1px solid #204fb3;
}
.bgcolor6 {
  background: linear-gradient(270deg, #64aef0 0%, #4b70ec 100%);
}
.bgcolor7 {
  background: linear-gradient(270deg, #3dabea 0%, #28a5ec 100%);
}
.bgcolor8 {
  background: linear-gradient(270deg, #09b9ff 0%, #4d68ff 100%);
}
.color1 {
  color: rgba(255, 255, 255, 0.9);
}
.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 .formSelect {
    input::placeholder {
      color: rgba(255, 255, 255, 0.2);
    }
  }
  ::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;
    padding: 0 26px;
    border: 1px solid #307ad9;
    box-sizing: border-box;
    cursor: pointer;
  }
}
.btnColor {
  color: #00ebfc;
}
.disableColor {
  color: #ccc;
  cursor: not-allowed;
}
::v-deep .el-descriptions {
  .el-descriptions__body {
    background-color: transparent;
    .el-descriptions-item__container {
      color: #ffffff;
      font-family: "Source Han Sans CN Regular";
    }
  }
}
</style>