董国庆
2026-01-23 fab6dd779165da5b0214893d2f75e0196172c788
Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/smartBuilding
5个文件已添加
11个文件已修改
875 ■■■■■ 已修改文件
estate-frontend-v2024/src/views/business/forms/edit-clientParams-form.jsx 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/forms/edit-project-form.jsx 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/common/constants.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/layout/Header/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/forms/edit-accidentMessage-form.jsx 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/screenSetting/forms/edit-account-form.jsx 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/assets.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/assets1.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/assets2.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/img/home/assets3.png 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/utils/request.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/header/index.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/home/index.vue 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/home/service.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/login/index.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/login/service.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
estate-frontend-v2024/src/views/business/forms/edit-clientParams-form.jsx
@@ -178,19 +178,20 @@
    // 构造 editableData
    const editableData = {
      name: data.name || "",
      logo: data.logo || "",
      logo: { name: data.logo },
      logoFile: data.logo ? [{
        uid: '-1',
        name: 'logo.png',
        status: 'done',
        url: data.logo
        url: 'http://47.108.113.190:8181/public/file/download' + data.logo
      }] : [],
      bigHiddenDanger: data.bigHiddenDanger !== undefined ? data.bigHiddenDanger : 1,
      generalHiddenDanger: data.generalHiddenDanger !== undefined ? data.generalHiddenDanger : 1,
      commentType: data.commentType !== undefined ? data.commentType : 1,
      safetyId: data.safetyId || undefined,
      deviceTemplateId: data.deviceTemplateId || undefined,
      projectNum: data.projectNum || "",
      housingProjectNum: data.housingProjectNum || "",
      municipalProjectNum: data.municipalProjectNum || "",
      id: data.id,
      clientId: clientInfo.id
    };
@@ -218,7 +219,8 @@
      commentType: data.commentType !== undefined ? data.commentType : 1, // 默认模糊
      safetyId: data.safetyId || undefined,
      deviceTemplateId: data.deviceTemplateId || undefined,
      projectNum: data.projectNum || "",
      housingProjectNum: data.housingProjectNum || "",
      municipalProjectNum: data.municipalProjectNum || "",
      id: data.id,
      clientId: data.clientId || data.id // 假设 currentRowData 就是 client 对象
    };
@@ -402,7 +404,7 @@
    const { getFieldDecorator } = form;
    const {
      name, logo, logoFile = [], bigHiddenDanger, generalHiddenDanger,
      commentType, safetyId, deviceTemplateId, projectNum
      commentType, safetyId, deviceTemplateId, housingProjectNum, municipalProjectNum
    } = this.state.editableData;
    const {
      dataSource, previewVisible, previewImage, assetRules, underConstruction, permissionEnabled,
@@ -580,17 +582,39 @@
                </Col>
                <Col span={24} style={{ marginTop: 16 }}>
                  <Form.Item label="委托方项目总数">
                    {getFieldDecorator("projectNum", {
                      rules: [{ required: true, message: "请输入委托方项目总数!" }],
                      initialValue: projectNum,
                    })(
                      <Input
                        style={{ width: "300px" }}
                        type="number"
                        placeholder="请输入项目数"
                      />,
                    )}
                  <Form.Item label="委托方项目总数" required>
                    <div style={{ display: 'flex', alignItems: 'center' }}>
                      <div style={{ display: 'flex', alignItems: 'center' }}>
                        <span>房建</span>
                        <Form.Item style={{ marginBottom: 0, marginLeft: 10 }}>
                          {getFieldDecorator("housingProjectNum", {
                            rules: [{ required: true, message: "请输入项目数!" }],
                            initialValue: housingProjectNum,
                          })(
                            <Input
                              style={{ width: "300px" }}
                              type="number"
                              placeholder="请输入项目数"
                            />
                          )}
                        </Form.Item>
                      </div>
                      <div style={{ display: 'flex', alignItems: 'center', marginLeft: 20 }}>
                        <span>市政</span>
                        <Form.Item style={{ marginBottom: 0, marginLeft: 10 }}>
                          {getFieldDecorator("municipalProjectNum", {
                            rules: [{ required: true, message: "请输入项目数!" }],
                            initialValue: municipalProjectNum,
                          })(
                            <Input
                              style={{ width: "300px" }}
                              type="number"
                              placeholder="请输入项目数"
                            />
                          )}
                        </Form.Item>
                      </div>
                    </div>
                  </Form.Item>
                </Col>
estate-frontend-v2024/src/views/business/forms/edit-project-form.jsx
@@ -57,6 +57,13 @@
        })
    }
    componentWillUnmount() {
        if (this.map) {
            this.map.destroy();
            this.map = null;
        }
    }
    getDepartmentRootFunc() {
        getDepartmentRoot().then((data) => {
            if (data.data.status === 'OK')
@@ -111,6 +118,12 @@
        let usageTypeList = projectTypeRelationMapNew[e.key]
        let usageType = usageTypeList && usageTypeList.length > 0 ? usageTypeList[0] : null
        this.setFieldValue('usageType', usageType)
        // 同时更新表单中的值,避免显示不同步
        const label = usageType ? projectUsageTypeMapNew[usageType] : '';
        this.props.form.setFieldsValue({
            usageType: { key: usageType || '', label: label || '' }
        });
    }
    refreshDistrictList = (city, cityLabel) => {
@@ -340,7 +353,7 @@
                        <div className="p-10">
                            <Form.Item label="项目类型:">
                                {getFieldDecorator("type", {
                                    initialValue: { key: type, label: projectTypeMapNew[type] },
                                    initialValue: type ? { key: type, label: projectTypeMapNew[type] } : { key: '', label: '' },
                                    rules: [{ required: true, message: '请选择项目类型!' }],
                                    onChange: (e) => this.handleTypeChange(e)
                                })(
estate-frontend-v2024/src/views/common/constants.js
@@ -4,7 +4,8 @@
// export const BASE_URL = 'http://47.93.28.249:8181'
export const BASE_URL = 'http://221.182.45.100:8180';
export const SCREEN_URL = 'http://221.182.45.100:8087/#/ ';
// export const SCREEN_URL = 'http://221.182.45.100:8087/#/ ';
export const SCREEN_URL = 'http://192.168.110.22:8087/#/ ';
// export const BASE_URL = 'http://localhost:8080';
@@ -211,8 +212,6 @@
export const reportTemplateTypeMap = new MapObject({
    ThirdPartyReport: '第三方评估报告',
    DeviceReport: '设备风险评估报告',
    0: '安全报告模板',
    1: '设备报告模板',
})
export const archiveTypeMap = new MapObject({
estate-frontend-v2024/src/views/layout/Header/index.jsx
@@ -140,7 +140,7 @@
      }
      const selectedProject = projectList.find(item => item.id === selectedProjectId);
      const projectName = selectedProject ? selectedProject.name : "";
      window.open(`${SCREEN_URL}?type=${tabsType}&token=${token}&projectId=${selectedProjectId}&projectName=${projectName}`, "_blank");
      window.open(`${SCREEN_URL}?type=${tabsType}&token=${token}&projectId=${1 || selectedProjectId}&projectName=${projectName}`, "_blank");
    }
  };
estate-frontend-v2024/src/views/screenSetting/forms/edit-accidentMessage-form.jsx
@@ -71,7 +71,7 @@
          // 如果是具体关键词(如山东省),districts[0] 是山东省,取其 children
          const root = data.districts[0];
          const list = root.districts || [];
          return list.map(node => ({
            value: node.name,
            label: node.name,
@@ -92,14 +92,14 @@
    targetOption.loading = true;
    const children = await this.getDistrictData(targetOption.label);
    targetOption.loading = false;
    if (children && children.length > 0) {
      targetOption.children = children;
    } else {
      targetOption.isLeaf = true;
    }
    this.setState({
      cityOptions: [...this.state.cityOptions],
    });
@@ -118,7 +118,7 @@
      detail: "",
      img: "",
      state: 1,
      cascaderValue: [],
      cascaderValue: [],
      file: [],
      editorState: EditorState.createEmpty(),
      previewVisible: false,
@@ -130,73 +130,74 @@
    let provinces = this.state.cityOptions;
    // 如果省份数据还没加载,先加载
    if (!provinces || provinces.length === 0) {
        provinces = await this.getDistrictData();
      provinces = await this.getDistrictData();
    }
    // 找到对应省份节点
    const provinceNode = provinces.find(p => p.value === province);
    if (provinceNode) {
        // 如果该省份没有子节点(市),加载市
        if (!provinceNode.children || provinceNode.children.length === 0) {
             const cities = await this.getDistrictData(province);
             provinceNode.children = cities;
      // 如果该省份没有子节点(市),加载市
      if (!provinceNode.children || provinceNode.children.length === 0) {
        const cities = await this.getDistrictData(province);
        provinceNode.children = cities;
      }
      // 如果有市,继续加载区
      if (city) {
        const cityNode = provinceNode.children.find(c => c.value === city);
        if (cityNode) {
          if (!cityNode.children || cityNode.children.length === 0) {
            const areas = await this.getDistrictData(city);
            cityNode.children = areas;
          }
        }
        // 如果有市,继续加载区
        if (city) {
            const cityNode = provinceNode.children.find(c => c.value === city);
            if (cityNode) {
                if (!cityNode.children || cityNode.children.length === 0) {
                    const areas = await this.getDistrictData(city);
                    cityNode.children = areas;
                }
            }
        }
      }
    }
    this.setState({ cityOptions: [...provinces] });
  }
  viewWillAppear() {
     const { detail, img, province, city, area } = this.state.editableData;
     let editorState = EditorState.createEmpty();
     if (detail) {
         const contentBlock = htmlToDraft(detail);
         if (contentBlock) {
             const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
             editorState = EditorState.createWithContent(contentState);
         }
     }
    const { detail, img, province, city, area } = this.state.editableData;
     let file = [];
     if (img) {
         file = [{
             uid: '-1',
             name: 'image.png',
             status: 'done',
             url: img
         }];
     }
    let editorState = EditorState.createEmpty();
    if (detail) {
      const contentBlock = htmlToDraft(detail);
      if (contentBlock) {
        const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
        editorState = EditorState.createWithContent(contentState);
      }
    }
     let cascaderValue = [];
     if (province) cascaderValue.push(province);
     if (city) cascaderValue.push(city);
     if (area) cascaderValue.push(area);
     // 预加载级联数据以支持回显
     if (province) {
         this.ensureCascaderData(province, city);
     }
    let file = [];
    if (img) {
      file = [{
        uid: '-1',
        name: 'image.png',
        status: 'done',
        url: 'http://47.108.113.190:8181/public/file/download' + img
      }];
    }
     this.setState({
         editableData: {
             ...this.state.editableData,
             editorState,
             file,
             cascaderValue
         }
     });
    let cascaderValue = [];
    if (province) cascaderValue.push(province);
    if (city) cascaderValue.push(city);
    if (area) cascaderValue.push(area);
    // 预加载级联数据以支持回显
    if (province) {
      this.ensureCascaderData(province, city);
    }
    this.setState({
      editableData: {
        ...this.state.editableData,
        editorState,
        file,
        img: { name: img },
        cascaderValue
      }
    });
  }
  onEditorStateChange = (editorState) => {
@@ -233,17 +234,17 @@
  };
  handleCascaderChange = (value) => {
      this.setFieldValue("cascaderValue", value);
      this.setFieldValue("province", value[0] || "");
      this.setFieldValue("city", value[1] || "");
      this.setFieldValue("area", value[2] || "");
    this.setFieldValue("cascaderValue", value);
    this.setFieldValue("province", value[0] || "");
    this.setFieldValue("city", value[1] || "");
    this.setFieldValue("area", value[2] || "");
  }
  handleUploadChange = ({ file, fileList }) => {
    this.setFieldValue("file", fileList);
    // 如果没有文件了,清空 img
    if (fileList.length === 0) {
        this.setFieldValue("img", "");
      this.setFieldValue("img", "");
    }
  }
@@ -293,7 +294,7 @@
                onChange: this.handleFieldChange("title"),
              })(<Input style={inputLongStyle} placeholder="请输入标题" />)}
            </Form.Item>
            <Form.Item label="类别">
              {getFieldDecorator("classifyId", {
                rules: [{ required: true, message: "请选择类别!" }],
@@ -302,7 +303,7 @@
              })(
                <Select style={inputLongStyle} placeholder="请选择类别">
                  {this.state.classificationOptions.map(option => (
                      <Option key={option.id} value={option.id}>{option.name}</Option>
                    <Option key={option.id} value={option.id}>{option.name}</Option>
                  ))}
                </Select>,
              )}
@@ -390,16 +391,16 @@
                <DatePicker showTime style={{ width: "250px" }} format={"YYYY-MM-DD HH:mm:ss"} />,
              )}
            </Form.Item>
            <Form.Item label="启用状态">
                {getFieldDecorator("state", {
              {getFieldDecorator("state", {
                rules: [{ required: true, message: "请选择启用状态!" }],
                initialValue: state,
                onChange: (value) => this.setFieldValue("state", value ? 1 : 2), // Switch返回bool,后端要1/2
                })(<Switch checked={state === 1} />)}
              })(<Switch checked={state === 1} />)}
            </Form.Item>
          </div>
          <Form.Item label="详情">
            {getFieldDecorator("detail", {
              rules: [{ required: true, message: "请输入详情" }],
estate-frontend-v2024/src/views/screenSetting/forms/edit-account-form.jsx
@@ -3,35 +3,54 @@
import "../style/index.less";
import EditFormBase from "../../common/edit-form-base";
import { inputLongStyle } from "../../common/constants";
import { getClientOptions } from "@/api/screenSetting";
import { getClientSelectOptions, getProjectSelectOptions } from "@/api/business";
const { Option } = Select;
class EditAccountForm extends EditFormBase {
  state = {
    ...this.state,
    clientOptions: []
    relationOptions: []
  };
  initView() {
    this.loadClientOptions();
  viewWillAppear() {
    const currentType = this.state.editableData.type || 1;
    this.loadOptions(currentType);
  }
  loadClientOptions = () => {
    getClientOptions().then(response => {
      if (response && response.data) {
        let options = [];
        if (response.data.data && Array.isArray(response.data.data)) {
          options = response.data.data;
        } else if (Array.isArray(response.data)) {
          options = response.data;
  loadOptions = (type) => {
    this.setState({ relationOptions: [] });
    if (type === 1) {
      getClientSelectOptions().then(response => {
        if (response && response.data) {
          let options = [];
          if (response.data.data && Array.isArray(response.data.data)) {
            options = response.data.data;
          } else if (Array.isArray(response.data)) {
            options = response.data;
          }
          this.setState({ relationOptions: options });
        }
        this.setState({ clientOptions: options });
      }
    }).catch(e => {
      console.error("加载委托方列表失败", e);
      this.setState({ clientOptions: [] });
    });
      }).catch(e => {
        console.error("加载委托方列表失败", e);
        this.setState({ relationOptions: [] });
      });
    } else {
      getProjectSelectOptions().then(response => {
        if (response && response.data) {
          let options = [];
          if (response.data.data && Array.isArray(response.data.data)) {
            options = response.data.data;
          } else if (Array.isArray(response.data)) {
            options = response.data;
          }
          this.setState({ relationOptions: options });
        }
      }).catch(e => {
        console.error("加载项目列表失败", e);
        this.setState({ relationOptions: [] });
      });
    }
  };
  initEditableData() {
@@ -43,6 +62,22 @@
      account: "",
      password: "",
    };
  }
  handleTypeChange = (e) => {
    const value = e.target.value;
    // Update form store (UI)
    this.props.form.setFieldsValue({
      clientProjectIds: []
    });
    // Update local state (EditFormBase)
    this.setFieldValue("type", value);
    this.setFieldValue("clientProjectIds", []);
    // Load options
    this.loadOptions(value);
  }
  render() {
@@ -79,7 +114,7 @@
            {getFieldDecorator("type", {
              rules: [{ required: true, message: "请选择级别!" }],
              initialValue: type,
              onChange: this.handleFieldChange("type"),
              onChange: this.handleTypeChange,
            })(
              <Radio.Group style={inputLongStyle}>
                <Radio value={1}>委托方</Radio>
@@ -87,16 +122,20 @@
              </Radio.Group>
            )}
          </Form.Item>
          <Form.Item label="关联委托方/项目">
          <Form.Item label={type == 1 ? '关联委托方' : '关联项目'}>
            {getFieldDecorator("clientProjectIds", {
              rules: [{ required: true, message: "请选择关联委托方/项目!" }],
              rules: [{ required: true, message: type == 1 ? '请选择关联委托方!' : '请选择关联项目!' }],
              initialValue: selectedClientIds,
              onChange: this.handleFieldChange("clientProjectIds"),
            })(
              <Select style={inputLongStyle} mode="multiple" placeholder="请选择关联委托方/项目">
                {this.state.clientOptions.map(option => (
                  <Option key={option.code} value={option.code.toString()}>{option.name}</Option>
                ))}
              <Select style={inputLongStyle} mode="multiple" placeholder={type == 1 ? '请选择关联委托方' : '请选择关联项目'}>
                {this.state.relationOptions.map(option => {
                  const value = (type === 1 ? option.code : option.id);
                  const finalValue = value !== undefined && value !== null ? value.toString() : "";
                  return (
                    <Option key={finalValue} value={finalValue}>{option.name}</Option>
                  );
                })}
              </Select>
            )}
          </Form.Item>
@@ -131,4 +170,4 @@
  }
}
export default Form.create({ name: "EditAccountForm" })(EditAccountForm);
export default Form.create({ name: "EditAccountForm" })(EditAccountForm);
screen/src/assets/img/home/assets.png
screen/src/assets/img/home/assets1.png
screen/src/assets/img/home/assets2.png
screen/src/assets/img/home/assets3.png
screen/src/utils/request.js
@@ -28,12 +28,19 @@
      return
    }
    const res = response
    if (res.data.code === 200 || res.data.status==='OK') {
    if (res.data.code === 200 || res.data.status === 'OK') {
      if (!res.data.data) {
        return Promise.resolve({})
        return Promise.resolve(res.data)
      }
      return Promise.resolve(res.data.data)
    } else {
      if (res.data.code === 401) {
        localStorage.clear()
        this.$router.replace({
          path: "/",
        });
      }
      if (res.data.code === 500) {
        return Promise.reject(res.data.data)
      }
screen/src/view/header/index.vue
@@ -1,11 +1,19 @@
<template>
  <div class="txt-center h--85 w100 relative imgBg">
    <div @click="toHome" class="flex a-center c-fff absolute adress1 cursor-pointer">
      <img src="../../assets/img/logo.png" class="w--30 h--30 shrink0 mr--10" />
      <div class="color2 lh--30 fs--30 SHSBold">成都市简州新城投资有限公司</div>
    <div
      @click="toHome"
      class="flex a-center c-fff absolute adress1 cursor-pointer"
    >
      <img
        :src="clientLogo || '../../assets/img/logo.png'"
        class="w--30 h--30 shrink0 mr--10"
      />
      <div class="color2 lh--30 fs--30 SHSBold">
        {{ clientName || "成都市简州新城投资有限公司" }}
      </div>
    </div>
    <div class="fs--43 lh--43 color3 SHSBold letter--6">
      {{ title || '智慧工程安全监管平台' }}
      {{ title || "智慧工程安全监管平台" }}
    </div>
    <div class="flex a-center c-fff absolute adress">
      <div class="txt-left fs--24 SHSBold">
@@ -21,12 +29,14 @@
  props: {
    title: {
      type: String,
      default: ''
    }
      default: "",
    },
  },
  data() {
    return {
      currentDate: "",
      clientName: localStorage.getItem("clientName"),
      clientLogo: localStorage.getItem("clientLogo"),
    };
  },
  mounted() {
@@ -40,12 +50,25 @@
  },
  methods: {
    toHome() {
      if (this.$route.path === "/home") {
        return;
      if (JSON.parse(localStorage.getItem("userInfo").type) == 2) {
        if (this.$route.path === "/projectHome") {
          return;
        }
        this.$router.replace({
          path: "/projectHome",
          query: {
            projectId: this.$route.query.projectId,
            projectName: this.$route.query.projectName,
          },
        });
      } else {
        if (this.$route.path === "/home") {
          return;
        }
        this.$router.replace({
          path: "/home",
        });
      }
      this.$router.replace({
        path: "/home",
      });
    },
    updateDateTime() {
      const now = new Date();
screen/src/view/home/index.vue
@@ -9,10 +9,10 @@
    <div
      class="flex a-center absolute postion-center top--109 br--16 c-fff fs--14 bgcolor4 SSHR"
    >
      <div @click="activeTab = 1" class="lh--32 px--20 cursor-pointer z-10">
      <div @click="changeTab(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 @click="changeTab(2)" class="lh--32 px--20 cursor-pointer z-10">
        固定资产
      </div>
      <div class="activeBox" :class="activeTab == 2 && 'activeBox2'">
@@ -33,16 +33,22 @@
            <div class="ripple-wave wave-3"></div>
          </div>
          <div class="fs--15 lh--15 ml--10">重大隐患数</div>
          <div class="color5 ml--13 fs--30 lh--30 zh_tr">16</div>
          <div class="color5 ml--13 fs--30 lh--30 zh_tr">
            {{ screenData.majorHazardTotal }}
          </div>
        </div>
        <div class="flex a-center j-center gap--52 mt--11">
          <div class="flex a-center">
            <div class="fs--14 lh--14 ml--10">未整改</div>
            <div class="color6 ml--13 fs--20 lh--24 zh_tr">14</div>
            <div class="color6 ml--13 fs--20 lh--24 zh_tr">
              {{ screenData.unrectifiedHazardCount }}
            </div>
          </div>
          <div class="flex a-center">
            <div class="fs--14 lh--14 ml--10">已整改</div>
            <div class="color7 ml--13 fs--20 lh--24 zh_tr">2</div>
            <div class="color7 ml--13 fs--20 lh--24 zh_tr">
              {{ screenData.rectifiedHazardCount }}
            </div>
          </div>
        </div>
      </div>
@@ -52,7 +58,10 @@
      class="absolute bottom--30 h--120 w--250 py--29 px--37 bgimg5"
      style="right: 505px"
    >
      <div class="flex a-center j-between fs--12 SHSR c-fff">
      <div
        v-if="activeTab == 1"
        class="flex a-center j-between fs--12 SHSR c-fff"
      >
        <div
          class="flex a-center gap--14 cursor-pointer"
          @click="toggleCategory('municipal')"
@@ -86,6 +95,24 @@
          <div :class="!categoryFilter.house && 'gray-text'">房建</div>
        </div>
      </div>
      <div v-else class="flex a-center j-center fs--12 SHSR c-fff">
        <div
          class="flex a-center gap--14 cursor-pointer"
          @click="toggleCategory('assets')"
        >
          <img
            v-if="categoryFilter.assets"
            src="../../assets/img/home/assets.png"
            class="w--18 h--16 shrink0"
          />
          <img
            v-else
            src="../../assets/img/home/assets.png"
            class="w--18 h--16 shrink0"
          />
          <div :class="!categoryFilter.assets && 'gray-text'">资产</div>
        </div>
      </div>
      <div class="flex a-center j-between gap--23 px--13 fs--12 SHSR mt--26">
        <div
          class="flex a-center flex-column cursor-pointer"
@@ -99,30 +126,30 @@
        </div>
        <div
          class="flex a-center flex-column cursor-pointer"
          @click="toggleLevel('B')"
        >
          <div
            class="w--8 h--8 mb--5 br50"
            :class="levelFilter.B ? 'bgcolor9' : 'gray-bg'"
          ></div>
          <div :class="levelFilter.B ? 'color9' : 'gray-text'">B类</div>
        </div>
        <div
          class="flex a-center flex-column cursor-pointer"
          @click="toggleLevel('C')"
        >
          <div
            class="w--8 h--8 mb--5 br50"
            :class="levelFilter.C ? 'bgcolor10' : 'gray-bg'"
          ></div>
          <div :class="levelFilter.C ? 'color10' : 'gray-text'">C类</div>
          <div :class="levelFilter.C ? 'color10' : 'gray-text'">B类</div>
        </div>
        <div
          class="flex a-center flex-column cursor-pointer"
          @click="toggleLevel('B')"
        >
          <div
            class="w--8 h--8 mb--5 br50"
            :class="levelFilter.B ? 'bgcolor9' : 'gray-bg'"
          ></div>
          <div :class="levelFilter.B ? 'color9' : 'gray-text'">C类</div>
        </div>
      </div>
    </div>
    <div class="leftBox">
      <div
        @click="handleClick"
        class="flex a-center j-between w100 px--20 h--40 relative bgcolor1 picker"
        class="flex a-center j-between w100 h--40 relative bgcolor1 picker"
      >
        <el-date-picker
          v-model="dateRange"
@@ -133,16 +160,25 @@
          end-placeholder=""
        >
        </el-date-picker>
        <div
          class="absolute w100 h100 flex a-center c-fff fs--14 SHS"
          style="width: calc(100% - 20px)"
        >
          {{ dateTxt }}
        <div class="absolute w100 h100 flex a-center px--20">
          <div
            class="flex a-center c-fff fs--14 SHS"
            style="width: calc(100% - 20px)"
          >
            {{ dateTxt }}
          </div>
          <div class="flex a-center gap--5">
            <i
              @click.stop="dateRange = []"
              class="el-icon-circle-close c-fff cursor-pointer"
              v-show="dateTxt"
            />
            <img
              src="../../assets/img/home/Shape@2x (6).png"
              class="w--13 h--13 shrink0"
            />
          </div>
        </div>
        <img
          src="../../assets/img/home/Shape@2x (6).png"
          class="w--13 h--13 shrink0"
        />
      </div>
      <div
        class="flex a-center j-between w100 pl--20 mt--13 h--40 relative bgcolor1 searchBox"
@@ -156,13 +192,23 @@
          >
          </el-option>
        </el-select>
        <div class="btn">搜索</div>
        <div
          class="flex a-center gap--5 absolute"
          style="top: -2px; right: -2px"
        >
          <i
            @click.stop="projectId = null"
            class="el-icon-circle-close c-fff cursor-pointer"
            v-show="projectId"
          />
          <div class="btn">搜索</div>
        </div>
      </div>
      <div class="mt--33 relative">
      <div v-if="permissionClient.includes('2')" class="mt--33 relative">
        <TitleBox>
          <template #title> 项目数据总览 </template>
          <template #content>
            <div class="flex px--20 mt--17 pb--16">
            <div class="flex j-center px--20 mt--17 pb--16">
              <div
                @click="toPorjectList"
                class="flex flex-column a-center mt--17 cursor-pointer"
@@ -176,10 +222,10 @@
                  class="color1 fs--34 lh--39 txts2 ff54-"
                  style="margin-top: -20px"
                >
                  99
                  {{ screenData.projectTotal }}
                </div>
              </div>
              <div class="ml--18">
              <div class="ml--18" v-if="activeTab == 1">
                <div
                  @click="toPorjectList"
                  class="flex a-center pl--11 pr--13 py--6 bgimg2 cursor-pointer thisBox relative"
@@ -197,55 +243,91 @@
                  >
                    <div class="c-fff SHSBold fs--15 lh--15">本月检查情况</div>
                    <div class="flex a-center j-between mt--20">
                      <div class="px--13 py--13 bsh1" style="min-width: 150px;">
                      <div class="px--13 py--13 bsh1" style="min-width: 150px">
                        <div class="c-fff fs---14 lh--14 SHSH">已检查数:</div>
                        <div class="fs--45 lh--45 ff54- color8">36</div>
                        <div class="fs--45 lh--45 ff54- color8">
                          {{ screenData.inspectedCount }}
                        </div>
                        <div class="mt--20 c-fff SHSR fs--13 lh--25">
                          <div>房建:30</div>
                          <div>市政:6</div>
                          <div>
                            房建:{{ screenData.inspectedHousingCount }}
                          </div>
                          <div>
                            市政:{{ screenData.inspectedMunicipalCount }}
                          </div>
                        </div>
                      </div>
                      <div class="px--13 py--13 bsh2" style="min-width: 150px;">
                      <div class="px--13 py--13 bsh2" style="min-width: 150px">
                        <div class="c-fff fs---14 lh--14 SHSH">未检查数:</div>
                        <div class="fs--45 lh--45 ff54- color6">36</div>
                        <div class="fs--45 lh--45 ff54- color6">
                          {{ screenData.uninspectedCount }}
                        </div>
                        <div class="mt--20 c-fff SHSR fs--13 lh--25">
                          <div>房建:30</div>
                          <div>市政:6</div>
                          <div>
                            房建:{{ screenData.uninspectedHousingCount }}
                          </div>
                          <div>
                            市政:{{ screenData.uninspectedMunicipalCount }}
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                <div class="mt--13 flex bgcolor2 pl--9 pb--5 pt--4 pr--10">
                  <div class="flex mt--7 shrink0">
                  <div class="flex flex1 mt--7 shrink0">
                    <img
                      src="../../assets/img/home/Shape@2x (5).png"
                      class="w--31 h--30 shrink0"
                    />
                    <div class="ml--7 SHSR">
                    <div class="ml--7 SHSR shrink0">
                      <div class="color2 fs--14 lh--14">房建</div>
                      <div class="mt--9 fs--8 lh--8 color3">本月检查覆盖率</div>
                      <div
                        v-if="!dateRange.length"
                        class="mt--9 fs--8 lh--8 color3"
                      >
                        本月检查覆盖率
                      </div>
                    </div>
                  </div>
                  <div class="ml--11">
                    <div class="c-fff fs--22 lh--22 SHSBold">62</div>
                    <div class="mt--9 fs--10 lh--12 color4 SHSM">50%</div>
                  <div class="ml--11 txt-center">
                    <div class="c-fff fs--22 lh--22 SHSBold">
                      {{ screenData.housingProjectCount }}
                    </div>
                    <div
                      v-if="!dateRange.length"
                      class="mt--9 fs--10 lh--12 color4 SHSM"
                    >
                      {{ screenData.housingInspectionCoverage }}%
                    </div>
                  </div>
                </div>
                <div class="mt--10 flex bgcolor2 pl--9 pb--5 pt--4 pr--10">
                  <div class="flex mt--7 shrink0">
                  <div class="flex flex1 mt--7 shrink0">
                    <img
                      src="../../assets/img/home/Combined Shape@2x (4).png"
                      class="w--30 h--30 shrink0"
                    />
                    <div class="ml--7 SHSR">
                    <div class="ml--7 SHSR shrink0">
                      <div class="color2 fs--14 lh--14">市政</div>
                      <div class="mt--9 fs--8 lh--8 color3">本月检查覆盖率</div>
                      <div
                        v-if="!dateRange.length"
                        class="mt--9 fs--8 lh--8 color3"
                      >
                        本月检查覆盖率
                      </div>
                    </div>
                  </div>
                  <div class="ml--11">
                    <div class="c-fff fs--22 lh--22 SHSBold">62</div>
                    <div class="mt--9 fs--10 lh--12 color4 SHSM">50%</div>
                  <div class="ml--11 txt-center">
                    <div class="c-fff fs--22 lh--22 SHSBold">
                      {{ screenData.municipalInspectionCoverage }}
                    </div>
                    <div
                      v-if="!dateRange.length"
                      class="mt--9 fs--10 lh--12 color4 SHSM"
                    >
                      {{ screenData.municipalInspectionCoverage }}%
                    </div>
                  </div>
                </div>
              </div>
@@ -275,20 +357,40 @@
                >
                  <div class="c-fff SHSBold fs--15 lh--15">本月检查情况</div>
                  <div class="flex a-center j-between mt--20">
                    <div class="px--13 py--13 bsh1" style="min-width: 150px;">
                    <div class="px--13 py--13 bsh1" style="min-width: 150px">
                      <div class="c-fff fs---14 lh--14 SHSH">已检查数:</div>
                      <div class="fs--45 lh--45 ff54- color8">36</div>
                      <div class="mt--20 c-fff SHSR fs--13 lh--25">
                        <div>塔式起重机:30</div>
                        <div>施工升降机:6</div>
                      <div class="fs--45 lh--45 ff54- color8">
                        {{ screenData.inspectedMachineryTotal }}
                      </div>
                      <div class="mt--20 h--50 oa">
                        <div
                          v-for="(
                            item, index
                          ) in screenData.machineryStatistics"
                          :key="index"
                          class="c-fff SHSR fs--13 lh--25"
                        >
                          <div>{{ item.name }}:{{ item.inspectedCount }}</div>
                        </div>
                      </div>
                    </div>
                    <div class="px--13 py--13 bsh2" style="min-width: 150px;">
                    <div class="px--13 py--13 bsh2" style="min-width: 150px">
                      <div class="c-fff fs---14 lh--14 SHSH">未检查数:</div>
                      <div class="fs--45 lh--45 ff54- color6">36</div>
                      <div class="mt--20 c-fff SHSR fs--13 lh--25">
                        <div>塔式起重机:30</div>
                        <div>施工升降机:6</div>
                      <div class="fs--45 lh--45 ff54- color6">
                        {{ screenData.uninspectedMachineryTotal }}
                      </div>
                      <div class="mt--20 h--50 oa">
                        <div
                          v-for="(
                            item, index
                          ) in screenData.machineryStatistics"
                          :key="index"
                          class="c-fff SHSR fs--13 lh--25"
                        >
                          <div>
                            {{ item.name }}:{{ item.uninspectedCount }}
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
@@ -304,23 +406,27 @@
                class="w--72 h--77 shrink0"
              />
              <div>
                <div class="fs--34 lh--39 color1 txts2 ff54-">6829</div>
                <div class="fs--34 lh--39 color1 txts2 ff54-">
                  {{ screenData.machineryTotal }}
                </div>
                <div class="c-fff fs--16 lh--16 SHSBold mt--10">
                  大型机械设备数
                </div>
              </div>
            </div>
            <div class="mt--14 mx--20 pb--10 rowItem">
            <div class="mt--14 mx--20 pb--10 rowItem h--250 oa">
              <div
                @click="toEquipmentList"
                v-for="item in 10"
                :key="item"
                v-for="(item, index) in screenData.machineryStatistics"
                :key="index"
                class="cursor-pointer"
              >
                <div class="bgimg3">
                  <div class="c-fff fs--22 lh--33 SHSBold txt-center">54</div>
                  <div class="c-fff fs--22 lh--33 SHSBold txt-center">
                    {{ item.total }}
                  </div>
                </div>
                <div class="fs--12 lh--12 color5 nameTxt">塔式起重机</div>
                <div class="fs--12 lh--12 color5 nameTxt">{{ item.name }}</div>
              </div>
            </div>
          </template>
@@ -473,6 +579,11 @@
import f1 from "../../assets/img/home/f1.png";
import f2 from "../../assets/img/home/f2.png";
import f3 from "../../assets/img/home/f3.png";
import z1 from "../../assets/img/home/assets1.png";
import z2 from "../../assets/img/home/assets2.png";
import z3 from "../../assets/img/home/assets3.png";
import { getStatistics } from "./service";
export default {
  components: {
    HeaderBox,
@@ -492,6 +603,7 @@
      categoryFilter: {
        municipal: true,
        house: true,
        assets: true,
      },
      levelFilter: {
        A: true,
@@ -499,6 +611,11 @@
        C: true,
      },
      markers: [],
      // 2项目总数(在建工程) 3大型机械设备数(在建工程) 4重大隐患数(在建工程) 5项目总数(固定资产) 6重大隐患数(固定资产) 7事故简讯 8工作展示
      permissionClient: JSON.parse(localStorage.getItem("permissionClient")),
      // 9各分项隐患趋势 10隐患数量 11设备数量 12查看报告入口 13人员在岗率 14重大风险源 15 项目风险趋势
      permissionProject: JSON.parse(localStorage.getItem("permissionProject")),
      screenData: {},
    };
  },
  watch: {
@@ -509,7 +626,10 @@
            moment(newVal[0]).format("YYYY年MM月DD日") +
            " ~ " +
            moment(newVal[1]).format("YYYY年MM月DD日");
        } else {
          this.dateTxt = "";
        }
        this.getScreenData();
      },
      immediate: true,
    },
@@ -519,9 +639,9 @@
      key: "232929db1cb31f26d42b3645a7456154",
      version: "2.0",
    });
    this.getScreenData();
  },
  mounted() {
    this.setMapload();
    this.$nextTick(() => {
      this.scrollContainer = this.$refs.scrollContainer;
      this.initScrollData();
@@ -531,6 +651,26 @@
    this.stopAutoScroll();
  },
  methods: {
    changeTab(type) {
      if (this.activeTab == type) return;
      this.activeTab = type;
      this.getScreenData();
    },
    getScreenData() {
      let params = {
        projectCategory: ["ongoing", "fixed"][this.activeTab - 1],
        startDate: "",
        endDate: "",
      };
      if (this.dateRange.length) {
        params.startDate = moment(this.dateRange[0]).format("YYYY-MM-DD");
        params.endDate = moment(this.dateRange[1]).format("YYYY-MM-DD");
      }
      getStatistics(params).then((res) => {
        this.screenData = res.ongoingProject || res.fixedAsset;
        this.setMapload();
      });
    },
    toAccidentCaseDetail(item) {
      this.$router.push({
        path: "/accidentCase/detail",
@@ -718,15 +858,10 @@
      }
      this.mapPromise
        .then((AMap) => {
          // 微信建筑图层
          let satellite = new AMap.TileLayer.Satellite();
          //创建路网图层
          let roadNet = new AMap.TileLayer.RoadNet();
          this.mapView = new AMap.Map("container", {
            zoom: 13,
            center: [104.065617, 30.656952], // 初始化地图中心点
            mapStyle: "amap://styles/darkblue",
            // layers: [satellite],
          });
          this.initCategoryMarkers(AMap);
        })
@@ -738,38 +873,14 @@
      if (!this.mapView) {
        return;
      }
      const points = [
        {
          position: [104.05, 30.65],
          category: "municipal",
          level: "A",
        },
        {
          position: [104.051, 30.651],
          category: "municipal",
          level: "B",
        },
        {
          position: [104.052, 30.652],
          category: "municipal",
          level: "C",
        },
        {
          position: [104.037471, 30.658643],
          category: "house",
          level: "A",
        },
        {
          position: [104.067471, 30.658643],
          category: "house",
          level: "B",
        },
        {
          position: [104.057471, 30.658643],
          category: "house",
          level: "C",
        },
      ];
      const points = this.screenData.projectMapPoints.map((item) => {
        return {
          ...item,
          position: [Number(item.longitude), Number(item.latitude)],
          category: ["house", "municipal", "assets"][item.projectType],
          level: item.category ? item.category.splice(0, 1) : "",
        };
      });
      const markers = [];
      points.forEach((item) => {
        const marker = this.createCategoryMarker(AMap, item);
@@ -786,7 +897,10 @@
        return null;
      }
      let image = null;
      if (item.category === "municipal") {
      let level = item.level;
      if (!level) {
        image = z3;
      } else if (item.category === "municipal") {
        if (item.level === "A") {
          image = s1;
        } else if (item.level === "B") {
@@ -801,6 +915,14 @@
          image = f2;
        } else if (item.level === "C") {
          image = f3;
        }
      } else if (item.category === "assets") {
        if (item.level === "A") {
          image = z1;
        } else if (item.level === "B") {
          image = z2;
        } else if (item.level === "C") {
          image = z3;
        }
      }
      if (!image) {
@@ -817,7 +939,7 @@
        offset: new AMap.Pixel(-12, -12),
        extData: {
          category: item.category,
          level: item.level,
          level: level,
        },
      });
      return marker;
@@ -835,7 +957,7 @@
          return;
        }
        const categoryVisible = this.categoryFilter[data.category];
        const levelVisible = this.levelFilter[data.level];
        const levelVisible = !data.level || this.levelFilter[data.level];
        if (categoryVisible && levelVisible) {
          marker.show();
        } else {
@@ -1073,9 +1195,6 @@
    }
    .btn {
      position: absolute;
      top: -2px;
      right: -2px;
      background: linear-gradient(
        90deg,
        #3467d0 0%,
screen/src/view/home/service.js
@@ -1,8 +1,8 @@
import request from '@/utils/request'
export const getDeptList = async (params) => {
  return request(`/statistics/deptList`, {
    method: 'get',
    params
export const getStatistics = async (data) => {
  return request(`/dashboard-statistics/index`, {
    method: 'post',
    data
  })
}
screen/src/view/login/index.vue
@@ -183,6 +183,7 @@
<script>
import { Message } from "element-ui";
import { loginApi, getProjectList, getLoginInfo } from "./service";
export default {
  components: {},
@@ -201,14 +202,10 @@
      },
      showPassword: false,
      showLoginBox: true,
      accountList: [
        { id: 1, name: "委托方名称111" },
        { id: 2, name: "委托方名称222" },
        { id: 3, name: "委托方名称333" },
        { id: 4, name: "委托方名称444" },
        { id: 5, name: "委托方名称555" },
      ],
      accountList: [],
      selectedAccount: null,
      userInfo: null,
      token: null,
    };
  },
  computed: {},
@@ -216,9 +213,7 @@
  created() {
    this.generateCaptcha();
  },
  mounted() {
    document.addEventListener("keydown", this.handleKeyDown);
  },
  mounted() {},
  methods: {
    // 生成验证码
    generateCaptcha() {
@@ -318,36 +313,72 @@
          message: "验证码错误",
          type: "warning",
        });
        this.refreshCaptcha();
        return false;
      }
      return true;
    },
    // 登录处理
    handleLogin() {
      if (this.validateForm()) {
        // 这里可以添加实际的登录逻辑
        console.log("登录信息:", {
          account: this.form.account,
        loginApi({
          username: this.form.account,
          password: this.form.password,
          captcha: this.form.captcha,
        });
        // 模拟登录成功,显示账号选择框
        this.showLoginBox = false;
        this.selectedAccount = null;
      }
    },
    // 监听当前页面是否按下了回车
    handleKeyDown(event) {
      if (event.key === "Enter") {
        if (this.showLoginBox) {
          this.handleLogin();
        } else {
          this.confirmSelect();
        }
        })
          .then((res) => {
            this.userInfo = res.userInfo;
            this.token = res.token;
            localStorage.setItem("userInfo", JSON.stringify(res.userInfo));
            localStorage.setItem("token", res.token);
            getProjectList({ userId: res.userInfo.userId }).then((re) => {
              if (re && re.length > 1) {
                this.accountList = re;
              } else {
                if (re.length == 1) {
                  getLoginInfo({
                    id: re[0].id,
                    type: res.userInfo.type,
                  }).then((r) => {
                    localStorage.setItem(
                      "permissionClient",
                      JSON.stringify(
                        r.permissionClient ? r.permissionClient.split(",") : []
                      )
                    );
                    localStorage.setItem("clientName", r.name);
                    localStorage.setItem("clientLogo", r.logo);
                    localStorage.setItem(
                      "permissionProject",
                      JSON.stringify(
                        r.permissionProject
                          ? r.permissionProject.split(",")
                          : []
                      )
                    );
                    if (this.userInfo.type == 2) {
                      this.$router.replace({
                        path: "/projectHome",
                        query: {
                          projectId: re[0].id,
                          projectName: re[0].name,
                        },
                      });
                    } else {
                      this.$router.replace({
                        path: "/home",
                      });
                    }
                  });
                }
              }
            });
            this.showLoginBox = false;
            this.selectedAccount = null;
          })
          .catch((err) => {
            this.refreshCaptcha();
          });
      }
    },
@@ -385,22 +416,46 @@
        const account = this.accountList.find(
          (item) => item.id === this.selectedAccount
        );
        console.log("选择的账号:", account);
        // 这里可以添加实际的登录逻辑
        // 模拟跳转到首页
        this.$router.push("/home");
        getLoginInfo({
          id: account.id,
          type: this.userInfo.type,
        }).then((re) => {
          localStorage.setItem(
            "permissionClient",
            JSON.stringify(
              re.permissionClient ? re.permissionClient.split(",") : []
            )
          );
          localStorage.setItem("clientName", re.name);
          localStorage.setItem("clientLogo", re.logo);
          localStorage.setItem(
            "permissionProject",
            JSON.stringify(
              re.permissionProject ? re.permissionProject.split(",") : []
            )
          );
          if (this.userInfo.type == 2) {
            this.$router.replace({
              path: "/projectHome",
              query: {
                projectId: account.id,
                projectName: account.name,
              },
            });
          } else {
            this.$router.replace({
              path: "/home",
            });
          }
          localStorage.setItem("userInfo", JSON.stringify(this.userInfo));
          localStorage.setItem("token", this.token);
        });
      } else {
        Message({
          message: "请先选择一个账号",
          type: "warning",
        });
      }
    },
    beforeDestroy() {
      // 组件销毁前移除事件监听器,避免内存泄漏
      document.removeEventListener("keydown", this.handleKeyDown);
    },
  },
};
screen/src/view/login/service.js
New file
@@ -0,0 +1,23 @@
import request from '@/utils/request'
export const loginApi = async (data) => {
  return request(`/login`, {
    method: 'post',
    data
  })
}
export const getProjectList = async (params) => {
  return request(`/project/getLoginNameVoList`, {
    method: 'get',
    params
  })
}
export const getLoginInfo = async (params) => {
  return request(`/dashboard-statistics/getLoginInfo`, {
    method: 'get',
    params
  })
}