tuqin
6 天以前 5794c7a46a0aa3d4fe5ece33c6bc84ca36494283
feat(safety): 安全生产三期 - 隐患排查治理前端

配套后端隐患接口。

新增:
- api/safety/hazard
- views/safety/hazard:隐患列表 + 登记表单 + 提交整改弹窗 + 验收弹窗
* 列表按状态动态显示可用操作:待整改/整改中显示「整改」,待验收显示「验收」,
已闭环隐藏编辑
* 整改期限超期用红色加粗 + 「超期」标签提示
* 验收弹窗通过/驳回二选一,选驳回时必须填原因(前端先拦一道)
- dict-enum.ts 补 3 个隐患字典常量

注:本期只提交代码,未部署。
已添加6个文件
已修改1个文件
821 ■■■■■ 文件已修改
src/api/safety/hazard/index.ts 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/packages/constants/src/dict-enum.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safety/hazard/data.ts 271 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safety/hazard/index.vue 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safety/hazard/modules/check.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safety/hazard/modules/form.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safety/hazard/modules/rectify.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/safety/hazard/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
import type { PageParam, PageResult } from '#/packages/effects/request/src';
import { requestClient } from '#/api/request';
export namespace MesSafetyHazardApi {
  /** é𐿂£ */
  export interface Hazard {
    id?: number;
    code?: string;
    name?: string;
    source?: number;
    hazardLevel?: number;
    category?: number;
    unitId?: number;
    unitName?: string;
    riskId?: number;
    riskName?: string;
    workshopId?: number;
    workshopName?: string;
    location?: string;
    description?: string;
    foundDate?: string;
    founderUserId?: number;
    founderUserName?: string;
    chargeUserId?: number;
    chargeUserName?: string;
    deadline?: string;
    rectifyRequirement?: string;
    status?: number;
    overdue?: boolean;
    measure?: string;
    finishDate?: string;
    checkUserId?: number;
    checkUserName?: string;
    checkTime?: string;
    checkResult?: string;
    rejectReason?: string;
    remark?: string;
    createTime?: string;
  }
  /** åˆ†é¡µå‚æ•° */
  export interface HazardPageParam extends PageParam {
    code?: string;
    name?: string;
    source?: number;
    hazardLevel?: number;
    status?: number;
    workshopId?: number;
    chargeUserId?: number;
    riskId?: number;
    foundDateStart?: string;
    foundDateEnd?: string;
  }
  /** æäº¤æ•´æ”¹å‚æ•° */
  export interface HazardRectifyParam {
    finishDate?: string;
    id: number;
    measure: string;
  }
  /** éªŒæ”¶å‚æ•° */
  export interface HazardCheckParam {
    checkResult?: string;
    id: number;
    pass: boolean;
    rejectReason?: string;
  }
}
/** æŸ¥è¯¢é𐿂£åˆ†é¡µ */
export function getHazardPage(params: MesSafetyHazardApi.HazardPageParam) {
  return requestClient.get<PageResult<MesSafetyHazardApi.Hazard>>(
    '/mes/safety/hazard/page',
    { params },
  );
}
/** æŸ¥è¯¢é𐿂£è¯¦æƒ… */
export function getHazard(id: number) {
  return requestClient.get<MesSafetyHazardApi.Hazard>(
    `/mes/safety/hazard/get?id=${id}`,
  );
}
/** ç™»è®°é𐿂£ */
export function createHazard(data: MesSafetyHazardApi.Hazard) {
  return requestClient.post<number>('/mes/safety/hazard/create', data);
}
/** æ›´æ–°é𐿂£ */
export function updateHazard(data: MesSafetyHazardApi.Hazard) {
  return requestClient.put<boolean>('/mes/safety/hazard/update', data);
}
/** åˆ é™¤é𐿂£ */
export function deleteHazard(id: number) {
  return requestClient.delete<boolean>(`/mes/safety/hazard/delete?id=${id}`);
}
/** æäº¤æ•´æ”¹ */
export function rectifyHazard(data: MesSafetyHazardApi.HazardRectifyParam) {
  return requestClient.put<boolean>('/mes/safety/hazard/rectify', data);
}
/** æ•´æ”¹éªŒæ”¶ */
export function checkHazard(data: MesSafetyHazardApi.HazardCheckParam) {
  return requestClient.put<boolean>('/mes/safety/hazard/check', data);
}
src/packages/constants/src/dict-enum.ts
@@ -309,6 +309,9 @@
  MES_SAFETY_RISK_CATEGORY: 'mes_safety_risk_category', // å®‰å…¨ç”Ÿäº§-风险类别
  MES_SAFETY_ACCIDENT_TYPE: 'mes_safety_accident_type', // å®‰å…¨ç”Ÿäº§-事故类型
  MES_SAFETY_UNIT_STATUS: 'mes_safety_unit_status', // å®‰å…¨ç”Ÿäº§-风险单元状态
  MES_SAFETY_HAZARD_SOURCE: 'mes_safety_hazard_source', // å®‰å…¨ç”Ÿäº§-隐患来源
  MES_SAFETY_HAZARD_LEVEL: 'mes_safety_hazard_level', // å®‰å…¨ç”Ÿäº§-隐患等级
  MES_SAFETY_HAZARD_STATUS: 'mes_safety_hazard_status', // å®‰å…¨ç”Ÿäº§-隐患状态
} as const;
/** ========== WMS - ä»“储管理模块 ========== */
src/views/safety/hazard/data.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,271 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesSafetyHazardApi } from '#/api/safety/hazard';
import { DICT_TYPE } from '#/packages/constants/src';
import { getDictOptions } from '#/packages/effects/hooks/src';
import { getRiskUnitSimpleList } from '#/api/safety/risk/unit';
import { getSimpleUserList, getWorkshopOptions } from '../risk/shared';
/** é𐿂£çŠ¶æ€å¸¸é‡ */
export const HAZARD_STATUS = {
  PENDING: 0,
  RECTIFYING: 10,
  TO_CHECK: 20,
  CLOSED: 30,
};
/** çŠ¶æ€åç§° */
export function hazardStatusName(status?: number): string {
  switch (status) {
    case 0: return '待整改';
    case 10: return '整改中';
    case 20: return '待验收';
    case 30: return '已闭环';
    default: return '-';
  }
}
/** çŠ¶æ€é¢œè‰² */
export function hazardStatusColor(status?: number): string {
  switch (status) {
    case 0: return 'error';
    case 10: return 'processing';
    case 20: return 'warning';
    case 30: return 'success';
    default: return 'default';
  }
}
/** åˆ—表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] {
  return [
    {
      fieldName: 'code',
      label: '隐患编码',
      component: 'Input',
      componentProps: { allowClear: true, placeholder: '请输入隐患编码' },
    },
    {
      fieldName: 'name',
      label: '隐患名称',
      component: 'Input',
      componentProps: { allowClear: true, placeholder: '请输入隐患名称' },
    },
    {
      fieldName: 'hazardLevel',
      label: '隐患等级',
      component: 'Select',
      componentProps: {
        allowClear: true,
        options: getDictOptions(DICT_TYPE.MES_SAFETY_HAZARD_LEVEL, 'number'),
        placeholder: '请选择隐患等级',
      },
    },
    {
      fieldName: 'status',
      label: '状态',
      component: 'Select',
      componentProps: {
        allowClear: true,
        options: getDictOptions(DICT_TYPE.MES_SAFETY_HAZARD_STATUS, 'number'),
        placeholder: '请选择状态',
      },
    },
  ];
}
/** ç™»è®°/修改的表单 */
export function useFormSchema(): VbenFormSchema[] {
  return [
    {
      fieldName: 'id',
      component: 'Input',
      dependencies: { triggerFields: [''], show: () => false },
    },
    {
      fieldName: 'code',
      label: '隐患编码',
      component: 'Input',
      componentProps: { placeholder: '如 YH-2026-001' },
      rules: 'required',
    },
    {
      fieldName: 'name',
      label: '隐患名称',
      component: 'Input',
      componentProps: { placeholder: '如 é…ç”µç®±ç¼ºé˜²æŠ¤ç½©' },
      rules: 'required',
    },
    {
      fieldName: 'source',
      label: '隐患来源',
      component: 'Select',
      componentProps: {
        allowClear: true,
        options: getDictOptions(DICT_TYPE.MES_SAFETY_HAZARD_SOURCE, 'number'),
        placeholder: '请选择隐患来源',
      },
    },
    {
      fieldName: 'hazardLevel',
      label: '隐患等级',
      component: 'Select',
      componentProps: {
        allowClear: true,
        options: getDictOptions(DICT_TYPE.MES_SAFETY_HAZARD_LEVEL, 'number'),
        placeholder: '请选择隐患等级',
      },
    },
    {
      fieldName: 'category',
      label: '隐患类别',
      component: 'Select',
      componentProps: {
        allowClear: true,
        options: getDictOptions(DICT_TYPE.MES_SAFETY_RISK_CATEGORY, 'number'),
        placeholder: '请选择隐患类别',
      },
    },
    {
      fieldName: 'unitId',
      label: '关联风险单元',
      component: 'ApiSelect',
      componentProps: {
        allowClear: true,
        api: getRiskUnitSimpleList,
        labelField: 'name',
        valueField: 'id',
        placeholder: '可关联到具体风险点',
      },
    },
    {
      fieldName: 'workshopId',
      label: '所属车间',
      component: 'ApiSelect',
      componentProps: {
        allowClear: true,
        api: getWorkshopOptions,
        labelField: 'name',
        valueField: 'id',
        placeholder: '请选择所属车间',
      },
    },
    {
      fieldName: 'location',
      label: '具体位置',
      component: 'Input',
      componentProps: { placeholder: '如 é€ çº¸è½¦é—´é…ç”µæˆ¿' },
    },
    {
      fieldName: 'description',
      label: '隐患描述',
      component: 'Textarea',
      formItemClass: 'col-span-2',
      componentProps: { placeholder: '请描述隐患的具体情况', rows: 3 },
    },
    {
      fieldName: 'foundDate',
      label: '发现日期',
      component: 'DatePicker',
      componentProps: {
        class: '!w-full',
        format: 'YYYY-MM-DD',
        valueFormat: 'YYYY-MM-DD',
        placeholder: '请选择发现日期',
      },
    },
    {
      fieldName: 'founderUserId',
      label: '发现人',
      component: 'ApiSelect',
      componentProps: {
        allowClear: true,
        api: getSimpleUserList,
        labelField: 'nickname',
        valueField: 'id',
        placeholder: '请选择发现人',
      },
    },
    {
      fieldName: 'chargeUserId',
      label: '整改责任人',
      component: 'ApiSelect',
      componentProps: {
        api: getSimpleUserList,
        labelField: 'nickname',
        valueField: 'id',
        placeholder: '请选择整改责任人',
      },
      rules: 'selectRequired',
    },
    {
      fieldName: 'deadline',
      label: '整改期限',
      component: 'DatePicker',
      componentProps: {
        class: '!w-full',
        format: 'YYYY-MM-DD',
        valueFormat: 'YYYY-MM-DD',
        placeholder: '请选择整改期限',
      },
    },
    {
      fieldName: 'rectifyRequirement',
      label: '整改要求',
      component: 'Textarea',
      formItemClass: 'col-span-2',
      componentProps: { placeholder: '请输入整改要求', rows: 2 },
    },
    {
      fieldName: 'remark',
      label: '备注',
      component: 'Textarea',
      formItemClass: 'col-span-2',
      componentProps: { placeholder: '请输入备注', rows: 2 },
    },
  ];
}
/** åˆ—表的字段 */
export function useGridColumns(): VxeTableGridOptions<MesSafetyHazardApi.Hazard>['columns'] {
  return [
    { field: 'code', title: '隐患编码', width: 140 },
    { field: 'name', title: '隐患名称', minWidth: 180 },
    {
      field: 'hazardLevel',
      title: '等级',
      width: 100,
      cellRender: {
        name: 'CellDict',
        props: { type: DICT_TYPE.MES_SAFETY_HAZARD_LEVEL },
      },
    },
    {
      field: 'source',
      title: '来源',
      width: 110,
      cellRender: {
        name: 'CellDict',
        props: { type: DICT_TYPE.MES_SAFETY_HAZARD_SOURCE },
      },
    },
    { field: 'workshopName', title: '车间', width: 110 },
    { field: 'location', title: '位置', minWidth: 140 },
    { field: 'chargeUserName', title: '整改责任人', width: 110 },
    { field: 'deadline', title: '整改期限', width: 120, slots: { default: 'deadline' } },
    {
      field: 'status',
      title: '状态',
      width: 100,
      slots: { default: 'status' },
    },
    {
      title: '操作',
      width: 240,
      fixed: 'right',
      slots: { default: 'actions' },
    },
  ];
}
src/views/safety/hazard/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,176 @@
<script lang="ts" setup>
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesSafetyHazardApi } from '#/api/safety/hazard';
import { Page } from '#/packages/effects/common-ui/src';
import { message, Tag } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteHazard, getHazardPage } from '#/api/safety/hazard';
import { useVbenModal } from '@vben/common-ui';
import {
  HAZARD_STATUS,
  hazardStatusColor,
  hazardStatusName,
  useGridColumns,
  useGridFormSchema,
} from './data';
import CheckModal from './modules/check.vue';
import FormModalComp from './modules/form.vue';
import RectifyModal from './modules/rectify.vue';
defineOptions({ name: 'SafetyHazard' });
const [FormModal, formModalApi] = useVbenModal({
  connectedComponent: FormModalComp,
  destroyOnClose: true,
});
const [RectifyModalComp, rectifyModalApi] = useVbenModal({
  connectedComponent: RectifyModal,
  destroyOnClose: true,
});
const [CheckModalComp, checkModalApi] = useVbenModal({
  connectedComponent: CheckModal,
  destroyOnClose: true,
});
const [Grid, gridApi] = useVbenVxeGrid({
  formOptions: {
    schema: useGridFormSchema(),
  },
  gridOptions: {
    columns: useGridColumns(),
    height: 'auto',
    keepSource: true,
    proxyConfig: {
      ajax: {
        query: async ({ page }, formValues) =>
          await getHazardPage({
            pageNo: page.currentPage,
            pageSize: page.pageSize,
            ...formValues,
          }),
      },
    },
    rowConfig: {
      keyField: 'id',
      isHover: true,
    },
    toolbarConfig: {
      refresh: true,
      search: true,
    },
  } as VxeTableGridOptions<MesSafetyHazardApi.Hazard>,
});
function handleCreate() {
  formModalApi.setData({ formType: 'create' }).open();
}
function handleEdit(row: MesSafetyHazardApi.Hazard) {
  formModalApi.setData({ formType: 'update', id: row.id }).open();
}
function handleRectify(row: MesSafetyHazardApi.Hazard) {
  rectifyModalApi.setData({ id: row.id, name: row.name }).open();
}
function handleCheck(row: MesSafetyHazardApi.Hazard) {
  checkModalApi
    .setData({ id: row.id, name: row.name, measure: row.measure })
    .open();
}
function handleRefresh() {
  gridApi.query();
}
async function handleDelete(row: MesSafetyHazardApi.Hazard) {
  await deleteHazard(row.id!);
  message.success('删除成功');
  gridApi.query();
}
</script>
<template>
  <Page auto-content-height>
    <FormModal @success="handleRefresh" />
    <RectifyModalComp @success="handleRefresh" />
    <CheckModalComp @success="handleRefresh" />
    <Grid>
      <template #toolbar-tools>
        <TableAction
          :actions="[
            {
              label: '登记隐患',
              type: 'primary',
              icon: ACTION_ICON.ADD,
              auth: ['mes:safety-hazard:create'],
              onClick: handleCreate,
            },
          ]"
        />
      </template>
      <template #deadline="{ row }">
        <span v-if="row.deadline" :class="row.overdue ? 'font-semibold text-red-600' : ''">
          {{ row.deadline }}
          <Tag v-if="row.overdue" color="error" class="ml-1">超期</Tag>
        </span>
        <span v-else class="text-gray-400">-</span>
      </template>
      <template #status="{ row }">
        <Tag :color="hazardStatusColor(row.status)">
          {{ hazardStatusName(row.status) }}
        </Tag>
      </template>
      <template #actions="{ row }">
        <TableAction
          :actions="[
            {
              label: '整改',
              type: 'link',
              auth: ['mes:safety-hazard:rectify'],
              ifShow:
                row.status === HAZARD_STATUS.PENDING ||
                row.status === HAZARD_STATUS.RECTIFYING,
              onClick: handleRectify.bind(null, row),
            },
            {
              label: '验收',
              type: 'link',
              auth: ['mes:safety-hazard:check'],
              ifShow: row.status === HAZARD_STATUS.TO_CHECK,
              onClick: handleCheck.bind(null, row),
            },
            {
              label: '编辑',
              type: 'link',
              icon: ACTION_ICON.EDIT,
              auth: ['mes:safety-hazard:update'],
              ifShow: row.status !== HAZARD_STATUS.CLOSED,
              onClick: handleEdit.bind(null, row),
            },
            {
              label: '删除',
              type: 'link',
              danger: true,
              icon: ACTION_ICON.DELETE,
              auth: ['mes:safety-hazard:delete'],
              popConfirm: {
                title: '确定删除该隐患记录吗?',
                confirm: handleDelete.bind(null, row),
              },
            },
          ]"
        />
      </template>
    </Grid>
  </Page>
</template>
src/views/safety/hazard/modules/check.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,98 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { Input, message, Radio } from 'ant-design-vue';
import { checkHazard } from '#/api/safety/hazard';
const emit = defineEmits(['success']);
const hazardId = ref<number>();
const hazardName = ref<string>();
const measure = ref<string>();
const passed = ref<boolean>(true);
const checkResult = ref<string>('');
const rejectReason = ref<string>('');
const loading = ref(false);
const [Modal, modalApi] = useVbenModal({
  async onConfirm() {
    if (!passed.value && !rejectReason.value.trim()) {
      message.warning('验收不通过时必须填写驳回原因');
      return;
    }
    loading.value = true;
    try {
      await checkHazard({
        id: hazardId.value!,
        pass: passed.value,
        checkResult: checkResult.value,
        rejectReason: rejectReason.value,
      });
      emit('success');
      message.success(passed.value ? '验收通过,隐患已闭环' : '已驳回,退回整改');
      await modalApi.close();
    } finally {
      loading.value = false;
    }
  },
  onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      return;
    }
    const data = modalApi.getData<{
      id: number;
      measure?: string;
      name?: string;
    }>();
    hazardId.value = data.id;
    hazardName.value = data.name;
    measure.value = data.measure;
    passed.value = true;
    checkResult.value = '';
    rejectReason.value = '';
  },
});
</script>
<template>
  <Modal title="整改验收" class="w-1/2">
    <div class="mx-4 flex flex-col gap-4">
      <div>
        <div class="mb-1 text-gray-600">隐患</div>
        <div class="font-medium">{{ hazardName ?? '-' }}</div>
      </div>
      <div>
        <div class="mb-1 text-gray-600">整改措施(提交内容)</div>
        <div class="rounded bg-gray-50 p-2">{{ measure || '-' }}</div>
      </div>
      <div>
        <div class="mb-1 text-gray-600">验收结论</div>
        <Radio.Group v-model:value="passed" button-style="solid">
          <Radio.Button :value="true">通过并闭环</Radio.Button>
          <Radio.Button :value="false">驳回重新整改</Radio.Button>
        </Radio.Group>
      </div>
      <div v-if="passed">
        <div class="mb-1 text-gray-600">验收意见</div>
        <Input.TextArea
          v-model:value="checkResult"
          :rows="2"
          placeholder="如:已整改到位"
        />
      </div>
      <div v-else>
        <div class="mb-1 text-gray-600">
          é©³å›žåŽŸå›  <span class="text-red-500">*</span>
        </div>
        <Input.TextArea
          v-model:value="rejectReason"
          :rows="2"
          placeholder="如:防护罩固定不牢,需重新安装"
        />
      </div>
    </div>
  </Modal>
</template>
src/views/safety/hazard/modules/form.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
<script lang="ts" setup>
import type { MesSafetyHazardApi } from '#/api/safety/hazard';
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import {
  createHazard,
  getHazard,
  updateHazard,
} from '#/api/safety/hazard';
import { useFormSchema } from '../data';
const emit = defineEmits(['success']);
const formType = ref<'create' | 'update'>('create');
const isUpdate = computed(() => formType.value === 'update');
const getTitle = computed(() =>
  isUpdate.value ? '修改隐患' : '登记隐患',
);
const [Form, formApi] = useVbenForm({
  commonConfig: {
    componentProps: { class: 'w-full' },
    formItemClass: 'col-span-1',
    labelWidth: 110,
  },
  wrapperClass: 'grid-cols-2',
  layout: 'horizontal',
  schema: useFormSchema(),
  showDefaultActions: false,
});
const [Modal, modalApi] = useVbenModal({
  async onConfirm() {
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    modalApi.lock();
    const data = (await formApi.getValues()) as MesSafetyHazardApi.Hazard;
    try {
      await (isUpdate.value ? updateHazard(data) : createHazard(data));
      emit('success');
      message.success('操作成功');
      await modalApi.close();
    } finally {
      modalApi.unlock();
    }
  },
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      return;
    }
    const data = modalApi.getData<{
      formType: 'create' | 'update';
      id?: number;
    }>();
    formType.value = data.formType;
    await formApi.resetForm();
    if (data?.id) {
      modalApi.lock();
      try {
        const hazard = await getHazard(data.id);
        await formApi.setValues(hazard);
      } finally {
        modalApi.unlock();
      }
    }
  },
});
</script>
<template>
  <Modal :title="getTitle" class="w-2/3">
    <Form class="mx-4" />
  </Modal>
</template>
src/views/safety/hazard/modules/rectify.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,80 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { DatePicker, Input, message } from 'ant-design-vue';
import { rectifyHazard } from '#/api/safety/hazard';
const emit = defineEmits(['success']);
const hazardId = ref<number>();
const hazardName = ref<string>();
const measure = ref<string>('');
const finishDate = ref<string>();
const loading = ref(false);
const [Modal, modalApi] = useVbenModal({
  async onConfirm() {
    if (!measure.value || measure.value.trim().length === 0) {
      message.warning('请填写整改措施');
      return;
    }
    loading.value = true;
    try {
      await rectifyHazard({
        id: hazardId.value!,
        measure: measure.value,
        finishDate: finishDate.value,
      });
      emit('success');
      message.success('已提交整改,等待验收');
      await modalApi.close();
    } finally {
      loading.value = false;
    }
  },
  onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      return;
    }
    const data = modalApi.getData<{ id: number; name?: string }>();
    hazardId.value = data.id;
    hazardName.value = data.name;
    measure.value = '';
    finishDate.value = undefined;
  },
});
</script>
<template>
  <Modal title="提交整改" class="w-1/2">
    <div class="mx-4 flex flex-col gap-4">
      <div>
        <div class="mb-1 text-gray-600">隐患</div>
        <div class="font-medium">{{ hazardName ?? '-' }}</div>
      </div>
      <div>
        <div class="mb-1 text-gray-600">
          æ•´æ”¹æŽªæ–½ <span class="text-red-500">*</span>
        </div>
        <Input.TextArea
          v-model:value="measure"
          :rows="4"
          placeholder="请填写实际采取的整改措施"
        />
      </div>
      <div>
        <div class="mb-1 text-gray-600">整改完成日期</div>
        <DatePicker
          v-model:value="finishDate"
          class="w-full"
          value-format="YYYY-MM-DD"
          format="YYYY-MM-DD"
          placeholder="不填则默认今天"
        />
      </div>
    </div>
  </Modal>
</template>