orderModal.vue 10.4 KB
<template>
  <div>
    <BasicModal
      v-bind="$attrs"
      width="30rem"
      :title="getTitle"
      @register="register"
      @cancel="handleCancel"
      @ok="handleOk"
      destroyOnClose
    >
      <div>
        <BasicForm @register="registerForm" />
        <div
          v-if="userInfo.isTargetTenant"
          style="display: flex; width: 70%; margin-left: 70px; margin-bottom: 18px"
        >
          <div
            style="display: flex; width: 130px; align-content: center; justify-content: center"
            class="inputTitle"
          >
            设备
          </div>
          <a-input placeholder="请选择" :disabled="true" v-model:value="selectedDeviceLabel" />
          <a-button type="primary" @click="goChooseDevice">选设备</a-button>
        </div>
        <div style="display: flex; width: 70%; margin-left: 70px">
          <div
            style="display: flex; width: 118px; align-content: center; justify-content: center"
            class="inputTitle"
          >
            报修人
          </div>
          <a-input placeholder="请选择" :disabled="true" v-model:value="selectedUsername" />
          <a-button type="primary" @click="goChoose">选人</a-button>
        </div>
      </div>
      <a-modal
        v-model:visible="userVisible"
        :title="userModalTitle"
        width="60vw"
        height="50vh"
        @ok="handleUserOk"
        @cancel="handleUserCancel"
      >
        <div style="padding: 20px; display: flex">
          <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" isOpen="true" />
          <div style="margin-top: 20px; margin-left: 30px">
            <a-radio-group v-model:value="selectedItem">
              <template v-for="item in Options" :key="`${item.id}`">
                <a-radio :style="radioStyle" :value="item">{{ item.username }}</a-radio>
              </template>
            </a-radio-group>
          </div>
        </div>
      </a-modal>
      <a-modal
        v-model:visible="deviceVisible"
        title="选择设备"
        width="70vw"
        height="40vh"
        @ok="handleDeviceOk"
        @cancel="handleDeviceCancel"
      >
        <div style="padding: 20px">
          <div style="display: flex; gap: 12px; margin-bottom: 12px">
            <a-input
              v-model:value="deviceSearchInfo.code"
              placeholder="请输入设备位号"
              allowClear
              style="width: 240px"
            />
            <a-input
              v-model:value="deviceSearchInfo.name"
              placeholder="请输入设备名称"
              allowClear
              style="width: 240px"
            />
            <a-button type="primary" @click="handleDeviceSearch">搜索</a-button>
            <a-button @click="handleDeviceReset">重置</a-button>
          </div>
          <BasicTable @register="registerDeviceTable" />
        </div>
      </a-modal>
    </BasicModal>
  </div>
</template>
<script setup lang="ts">
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { BasicForm, useForm } from '/@/components/Form';
  import { computed, reactive, ref, unref } from 'vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { schemas } from '../index';
  import { getUserListByOrg } from '/@/api/equipment/ledger';
  import { useUserStore } from '/@/store/modules/user';
  import { saveOrder } from '/@/api/repair/order';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree';
  import { BasicTable, useTable } from '/@/components/Table';
  import { getLedgerList } from '/@/api/equipment/ledger';
  const { t } = useI18n();
  const isUpdate = ref<Boolean>(false);
  const recordInfo = ref<any>({});
  // 定义人员选项
  const userInfo = useUserStore();
  const { createMessage } = useMessage();

  const userOptions = ref([]);
  const Options = ref([]);
  const searchInfo = reactive<Recordable>({});
  const { organizationIdTreeRef } = useResetOrganizationTree(searchInfo);
  const userVisible = ref(false);
  const userModalTitle = ref('选人');
  const selectedItem = ref<{ id: string; username: string } | null>(null);
  const deviceVisible = ref(false);
  const deviceSearchInfo = reactive<Recordable>({ code: '', name: '' });
  const selectedDevice = ref<any>(null);
  const radioStyle = reactive({
    display: 'block',
    height: '30px',
    lineHeight: '30px',
  });
  // 计算属性实现双向绑定
  const selectedUsername = computed({
    get: () => selectedItem.value?.username || '',
    set: (value) => {
      if (selectedItem.value) {
        selectedItem.value.username = value;
      }
    },
  });

  const selectedDeviceLabel = computed({
    get: () => {
      const code = selectedDevice.value?.code;
      const name = selectedDevice.value?.name;
      if (code && name) return `${code} / ${name}`;
      return name || code || '';
    },
    set: () => {},
  });

  const emit = defineEmits(['handleReload', 'register']);

  const getTitle = computed(() =>
    !unref(isUpdate) ? t('repair.order.createOrderText') : t('repair.order.editOrderText')
  );

  const [registerForm, { getFieldsValue, setFieldsValue, validate, updateSchema }] = useForm({
    labelWidth: 140,
    schemas,
    actionColOptions: {
      span: 14,
    },
    showActionButtonGroup: false,
  });

  const [registerDeviceTable, { reload: reloadDeviceTable }] = useTable({
    api: getLedgerList,
    columns: [
      { title: '设备位号', dataIndex: 'code', width: 160 },
      { title: '设备名称', dataIndex: 'name', width: 240 },
    ],
    searchInfo: deviceSearchInfo,
    useSearchForm: false,
    showTableSetting: false,
    bordered: true,
    showIndexColumn: false,
    clickToRowSelect: false,
    rowKey: 'id',
    pagination: { pageSize: 10 },
    rowSelection: {
      type: 'radio',
      onSelect: (record) => {
        selectedDevice.value = record;
      },
      onSelectAll: () => {},
    },
  });

  const [register, { closeModal, setModalProps }] = useModalInner(async (data) => {
    setModalProps({ confirmLoading: false, loading: true });
    isUpdate.value = data?.isUpdate;
    recordInfo.value = data?.record;
    if (!selectedItem.value) {
      selectedItem.value = { id: '', username: '' };
    }
    selectedItem.value.username = data?.record?.reportByName || '';
    selectedItem.value.id = data?.record?.reportBy || '';
    updateSchema({
      field: 'situationImg',
      componentProps: {
        onChange: handleOrgChange,
      },
    });
    if (userInfo.isTargetTenant) {
      updateSchema({
        field: 'deviceId',
        ifShow: false,
      });
      selectedDevice.value = data?.record?.deviceInfo
        ? {
            id: data?.record?.deviceId,
            name: data?.record?.deviceInfo?.name,
            code: data?.record?.deviceInfo?.code,
          }
        : data?.record?.deviceId
        ? { id: data?.record?.deviceId, name: '' }
        : null;
    } else {
      updateSchema({
        field: 'deviceId',
        ifShow: true,
      });
      selectedDevice.value = null;
    }
    if (data?.record) {
      setFieldsValue(data?.record);
    }
    setModalProps({ loading: false });
  });

  // 监听 org 字段的变化
  const handleOrgChange = async (orgId: string) => {
    if (!orgId) {
      userOptions.value = []; // 清空人员选项
      updateSchema({
        field: 'report',
        componentProps: { options: [] },
      });
      return;
    }
    const _data = {
      page: '1',
      pageSize: '999',
      tenantId: userInfo.getUserInfo.tenantId!,
      organizationId: orgId,
    };
    // 调用接口 B 获取人员数据
    const userList = await getUserListByOrg(_data);
    userOptions.value = userList?.items.map((user) => ({
      label: user.username,
      value: user.id,
    }));

    // 更新 user 字段的选项
    updateSchema({
      field: 'report',
      componentProps: { options: userOptions.value },
    });
  };

  const handleCancel = () => {
    closeModal();
  };

  const handleOk = async () => {
    await validate();
    let values = getFieldsValue();
    if (userInfo.isTargetTenant && !selectedDevice.value?.id) {
      createMessage.warning('请选择设备');
      return;
    }
    if (!selectedItem?.value?.id) {
      createMessage.warning('请选择报修人');
      return;
    }
    if (unref(isUpdate)) {
      values = {
        ...values,
        id: unref(recordInfo).id,
        situationImg: values.image?.[0]?.url,
        reportBy: selectedItem.value?.id || '',
      };
    } else {
      values = {
        ...values,
        situationImg: values.image?.[0]?.url,
        reportBy: selectedItem.value?.id || '',
      };
    }
    if (userInfo.isTargetTenant) {
      values = { ...values, deviceId: selectedDevice.value?.id };
    }
    await saveOrder(values);
    createMessage.success(t('common.operationSuccessText'));
    emit('handleReload');
    handleCancel();
  };

  const goChoose = () => {
    userVisible.value = true;
    selectedItem.value = null;
  };

  const goChooseDevice = () => {
    deviceVisible.value = true;
    reloadDeviceTable();
  };

  const handleDeviceSearch = () => {
    reloadDeviceTable();
  };

  const handleDeviceReset = () => {
    deviceSearchInfo.code = '';
    deviceSearchInfo.name = '';
    reloadDeviceTable();
  };

  const handleDeviceOk = async () => {
    if (!selectedDevice.value?.id) {
      createMessage.warning('请选择设备');
      return;
    }
    await setFieldsValue({ deviceId: selectedDevice.value.id });
    deviceVisible.value = false;
  };

  const handleDeviceCancel = () => {
    deviceVisible.value = false;
  };

  // 确认按钮的回调
  const handleUserOk = () => {
    if (!selectedItem.value) {
      createMessage.warning('请选择一个用户');
      return;
    }

    userVisible.value = false; // 关闭弹框
  };

  const handleUserCancel = () => {
    selectedItem.value = null;
    userVisible.value = false;
  };

  const handleSelect = async (organizationId: string) => {
    searchInfo.organizationId = organizationId;
    const _data = {
      page: '1',
      pageSize: '999',
      tenantId: userInfo.getUserInfo.tenantId!,
      organizationId: organizationId,
    };
    const response = await getUserListByOrg(_data); // 调用接口
    Options.value = response.items;
  };
</script>
<style scoped>
.inputTitle::before {
  display: inline-block;
  margin-right: 4px;
  color: #ff4d4f;
  font-size: 14px;
  font-family: SimSun, sans-serif;
  line-height: 1;
  content: '*';
}
</style>