zhengyiming
4 天以前 5664a1a616df498cba58b9a8e63a91ac0ba96bab
src/views/Home/Home.vue
@@ -17,16 +17,7 @@
          </QueryFilterItem>
          <QueryFilterItem>
            <FieldRadio
              v-model="extraParamState.onJobFlag"
              :value-enum="OnJobFlagEnumText"
              buttonStyle
              showAllBtn
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem>
            <FieldRadio
              v-model="extraParamState.insuranceType"
              v-model="extraParamState.insurancePeriod"
              :value-enum="insuranceTypeText"
              buttonStyle
              showAllBtn
@@ -34,10 +25,28 @@
            />
          </QueryFilterItem>
          <QueryFilterItem>
            <FieldRadio
              v-model="extraParamState.auditStatus"
              :value-enum="InsurancePolicyAuditStatusEnumText"
              buttonStyle
              showAllBtn
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem>
            <FieldRadio
              v-model="extraParamState.status"
              :value-enum="InsurancePolicyStatusEnumText"
              buttonStyle
              showAllBtn
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem>
            <SearchInput
              v-model="extraParamState.keyword"
              v-model="extraParamState.condition"
              style="width: 260px"
              placeholder="姓名/身份证/单位/保单号等"
              placeholder="单位/保单号/参保机构"
              @on-click-search="getList"
            >
            </SearchInput>
@@ -45,60 +54,64 @@
        </template>
        <template #btn>
          <el-button
            @click="handleDownload()"
            icon="Download"
            @click="handleDownloadOccupationType()"
            type="primary"
            style="margin-right: 10px"
            link
            >职业类型对照表</el-button
          >
          <el-button @click="handleDownload()" type="primary" style="margin-right: 10px" link
            >模板下载</el-button
          >
          <BlFileUpload
            :limitFileSize="10"
            accept="xls,xlsx"
            :showTip="false"
            :show-file-list="false"
            :on-success="handleUploadSuccess"
          <el-button @click="handleUpload()" type="primary" style="margin-right: 10px"
            >导入投保人员</el-button
          >
            <template #default>
              <el-button icon="Plus" type="primary">导入</el-button>
            </template>
          </BlFileUpload>
          <el-button
            @click="handleEnterpriseBatchRefund()"
          <!-- <el-button
            v-if="AppType === 'jx'"
            @click="handleUpload()"
            type="primary"
            style="margin-right: 10px"
            >批量减员</el-button
          >
          <el-button
            @click="handleExport()"
            icon="Download"
            type="primary"
            style="margin-left: 10px"
            >导出</el-button
            >大批量数据导入</el-button
          > -->
          <el-button @click="getInsurancePageExport()" type="primary" link>导出保单列表</el-button>
          <el-button @click="getInsuranceStaffPageExport()" type="primary" link
            >导出在保人员</el-button
          >
        </template>
      </ProTableQueryFilterBar>
      <ProTableV2
        v-bind="proTableProps"
        :columns="HomeColumns"
        :columns="columns"
        :operationBtns="operationBtns"
        :show-column-check="true"
        :column-selectable="columnSelectable"
        ref="proTable"
        :table-props="{
          rowStyle: handleRowStyle,
          rowKey: 'id',
        }"
      >
        <template #auditStatus="{ row }">
          <el-tooltip
            class="box-item"
            effect="dark"
            :content="row.auditRemark"
            placement="top"
            v-if="row.auditStatus === InsurancePolicyAuditStatusEnum.Reject && row.auditRemark"
            popper-class="max-width-popper"
          >
            <div style="display: inline-flex; align-items: center; color: inherit">
              {{ InsurancePolicyAuditStatusEnumText[row.auditStatus] }}
              <el-icon size="16" color="#3a71ff"><QuestionFilled /></el-icon>
            </div>
          </el-tooltip>
          <el-text v-else style="color: inherit">
            {{ InsurancePolicyAuditStatusEnumText[row.auditStatus] }}
          </el-text>
        </template>
      </ProTableV2>
    </AppContainer>
    <UploadMaterialDialog
      v-bind="dialogProps"
      @onAddUpdateMaterial="getList(paginationState.pageIndex)"
    />
    <BatchDownsizingDialog v-bind="dialogBatchDownsizingProps" />
    <UploadInsurePersonDialog v-bind="dialogProps" />
    <UploadStampFileDialog v-bind="dialogStampFileProps" />
    <InsureInstructionsDialog v-bind="dialogInstructionsProps" />
  </LoadingLayout>
</template>
@@ -112,30 +125,37 @@
  useTable,
  useFormDialog,
  FieldDatePicker,
  BlFileUpload,
  defineOperationBtns,
  UploadUserFile,
  XLSXUtils,
  SearchInput,
  FieldRadio,
  XLSXUtils,
  useDialog,
} from '@bole-core/components';
import * as insuranceOrderServices from '@/services/api/InsuranceOrder';
import { Message, OrderInputType, downloadFileByUrl } from '@bole-core/core';
import { HomeColumns } from './constants';
import UploadMaterialDialog from './components/UploadMaterialDialog.vue';
import BatchDownsizingDialog from './components/BatchDownsizingDialog.vue';
import { toThousand, format, downloadFile, setOSSLink } from '@/utils';
import { omit } from 'lodash';
import { columns } from './constants';
import UploadInsurePersonDialog from './components/UploadInsurePersonDialog.vue';
import UploadStampFileDialog from './components/UploadStampFileDialog.vue';
import { format, downloadFile, setOSSLink, toThousand, convertApi2FormUrl } from '@/utils';
import { ModelValueType } from 'element-plus';
import { useQueryClient } from '@tanstack/vue-query';
import {
  InsuranceOrderTempPath,
  JYBInsuranceOrderTempPath,
  OnJobFlagEnumText,
  insuranceTypeText,
  InsurancePolicyStatusEnumText,
  InsurancePolicyStatusEnum,
  AppType,
  InsurancePolicyAuditStatusEnumText,
  InsurancePolicyAuditStatusEnum,
  InsurancePolicyProductIdNumberEnum,
  InsurancePolicyListPayStatusEnum,
  InsurancePolicyListPayStatusEnumText,
  InsuranceOccupationTypeTempPath,
} from '@/constants';
import dayjs from 'dayjs';
import _ from 'lodash';
import InsureInstructionsDialog from './components/InsureInstructionsDialog.vue';
// import { Recorder } from '@/utils/record';
defineOptions({
  name: 'Home',
@@ -144,32 +164,121 @@
const operationBtns = defineOperationBtns([
  {
    data: {
      enCode: 'detailBtn',
      name: '详情',
    },
    emits: {
      onClick: (role) => handleDetail(role),
    },
  },
  {
    data: {
      enCode: 'batchBtn',
      name: '批改',
    },
    emits: {
      onClick: (role) => handleBatch(role),
    },
    extraProps: {
      hide: (row: API.GetInsurancePageOutput) =>
        row.productOnline || row.status !== InsurancePolicyStatusEnum.Effecting,
    },
  },
  {
    data: {
      enCode: 'uploadStampFileBtn',
      name: '上传盖章文件',
    },
    emits: {
      onClick: (role) => handleUploadStampFile(role),
    },
    extraProps: {
      hide: (row: API.GetInsurancePageOutput) =>
        row.status !== InsurancePolicyStatusEnum.WaitEffect,
    },
  },
  {
    data: {
      enCode: 'downloadBtn',
      name: '保单下载',
    },
    emits: {
      onClick: (role) => handleDownloadOrderNo(role),
      onClick: (role) => handleDownloadInsureFile(role),
    },
    extraProps: {
      hide: (row: API.InsuranceOrderListOutput) => !row.orderBillFile,
      hide: (row: API.GetInsurancePageOutput) => row.productOnline || !row.insureBillUrl,
    },
  },
]).filter(Boolean);
  {
    data: {
      enCode: 'payBtn',
      name: '支付',
    },
    emits: {
      onClick: (role) => handlePay(role),
    },
    extraProps: {
      hide: (row: API.GetInsurancePageOutput) =>
        row.payStatus != InsurancePolicyListPayStatusEnum.WaitPay,
    },
  },
  {
    data: {
      enCode: 'stampFilesBtn',
      name: '保单下载',
    },
    emits: {
      onClick: (role) => handleGoStampFiles(role),
    },
    extraProps: {
      hide: (row: API.GetInsurancePageOutput) => !(row.productOnline && row.anyPayComplete),
    },
  },
  {
    data: {
      enCode: 'downloadInvoiceBtn',
      name: '发票下载',
    },
    emits: {
      onClick: (role) => handleGoDownloadInvoice(role),
    },
    extraProps: {
      hide: (row: API.GetInsurancePageOutput) => !(row.productOnline && row.anyPayComplete),
    },
  },
const columnSelectable = (row: API.InsuranceOrderListOutput) => {
  return row.onJobFlag === '增员';
};
  // {
  //   data: {
  //     enCode: 'standarEndoBtn',
  //     name: '申请退保',
  //   },
  //   emits: {
  //     onClick: (role) => handleStandarEndo(role),
  //   },
  // },
]).filter(Boolean);
const BaseState = {
  loading: true,
};
const state = reactive({ ...BaseState });
// const recorder = ref(new Recorder());
onMounted(async () => {
  await getList();
  state.loading = false;
  handleOpenInstructions();
  // setTimeout(() => {
  //   // recorder.value.init();
  //   recorder.value.replaySession('9cb24e5a-0423-4dcd-abd5-fa7a4117cadc');
  // }, 3000);
});
// onUnmounted(() => {
//   recorder.value.stopRecordingAndSave();
// });
const {
  getDataSource: getList,
@@ -181,7 +290,7 @@
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params = createParams(pageIndex, pageSize);
      let res = await insuranceOrderServices.getInsuranceOrderPage(params, {
      let res = await insuranceOrderServices.getInsurancePage(params, {
        showLoading: !state.loading,
      });
      return res;
@@ -189,116 +298,136 @@
  },
  {
    defaultExtraParams: {
      orderInput: [{ property: 'createTime', order: OrderInputType.Desc }],
      orderInput: [{ property: 'id', order: OrderInputType.Desc }],
      creationDate: [] as unknown as ModelValueType,
      keyword: '',
      onJobFlag: '',
      insuranceType: '',
      condition: '',
      status: '' as any as InsurancePolicyStatusEnum,
      auditStatus: '' as any as InsurancePolicyAuditStatusEnum,
      insurancePeriod: '',
    },
    columnsRenderProps: {
      createTime: {
        type: 'date',
        format: 'YYYY/MM/DD',
      status: { type: 'enum', valueEnum: InsurancePolicyStatusEnumText },
      insurancePeriod: { type: 'enum', valueEnum: insuranceTypeText },
      creationTime: { type: 'date', format: 'YYYY-MM-DD' },
      effectStartTime: { type: 'date', format: 'YYYY-MM-DD' },
      effectEndTime: { type: 'date', format: 'YYYY-MM-DD' },
      sumInsured: {
        type: 'money',
        formatter: (row: API.GetInsurancePageOutput) =>
          row.sumInsured == null ? '' : toThousand(row.sumInsured),
      },
      insuranceBeginTime: {
        type: 'date',
        format: 'YYYY/MM/DD',
      amount: {
        type: 'money',
        formatter: (row: API.GetInsurancePageOutput) =>
          row.amount == null ? '' : toThousand(row.amount),
      },
      insuranceEndTime: {
        type: 'date',
        format: 'YYYY/MM/DD',
      },
      payStatus: { type: 'enum', valueEnum: InsurancePolicyListPayStatusEnumText },
    },
    showSummary: true,
    summaryPropertys: [
      {
        property: 'table-operation',
        valueKey: 'totalAmount',
        formatter: (v) => `¥${toThousand(v)}`,
      },
    ],
  }
);
function createParams(pageIndex: number, pageSize: number) {
  let params: API.QueryInsuranceOrderPageInput = {
  let params: API.GetInsurancePageInput = {
    pageModel: {
      rows: pageSize,
      page: pageIndex,
      orderInput: extraParamState.orderInput,
    },
    beginCreationTime: format(extraParamState.creationDate?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
    endCreationTime: format(extraParamState.creationDate?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
    condition: extraParamState.keyword,
    onJobFlag: extraParamState.onJobFlag,
    insuranceType: extraParamState.insuranceType,
    importStartDateTime: format(extraParamState.creationDate?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
    importEndDateTime: format(extraParamState.creationDate?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
    condition: extraParamState.condition,
    insurancePeriod: extraParamState.insurancePeriod,
    status: extraParamState.status,
    auditStatus: extraParamState.auditStatus,
  };
  return params;
}
const queryClient = useQueryClient();
const { dialogProps, handleAdd, editForm, dialogState } = useFormDialog({
  onConfirm: checkInrancesSerialNumStatus,
  defaultFormParams: {
    serialNum: '',
    url: [] as UploadUserFile[],
    productIdNumber: '',
    productSchemeIdNumber: '',
  },
  closeAfterConfirm: false,
});
async function handleUploadSuccess(response: UploadUserFile) {
async function checkInrancesSerialNumStatus() {
  try {
    let res = await insuranceOrderServices.importInsuranceOrderData(response.url, {
      getResponse: true,
      responseType: 'blob',
    });
    if (res?.data?.size) {
      await Message.tipMessage('存在错误数据,是否导出?');
      downloadFile(res.data, `错误人员名单`, 'xlsx');
      // XLSXUtils.exportToXLSX({
      //   workbookDataList: res,
      //   fileName: '错误人员名单',
      //   workbookHeaderMap: {
      //     ...omit(Object.fromEntries(HomeColumns.map((x) => [x.enCode, x.name])), [
      //       'channel',
      //       'salesmanName',
      //       'createTime',
      //     ]),
      //     erroMsg: '备注',
      //   },
      // });
    let params: API.APIimportInsStaffToListParams = {
      serialNum: editForm.serialNum,
      url: editForm.url?.[0]?.path,
    };
    let res = await insuranceOrderServices.checkInrancesSerialNumStatus(params);
    if (res === InsurancePolicyStatusEnum.Effecting) {
      await Message.tipMessage('该批次保单已生效,请修改批次号后重新导入');
    } else if (res === InsurancePolicyStatusEnum.OutTimeEffect) {
      await Message.tipMessage('该批次保单已失效,请修改批次号后重新导入');
    } else if (res === InsurancePolicyStatusEnum.WaitEffect) {
      await Message.tipMessage('存在相同的批次号,是否覆盖?');
      importInsStaffToList();
    } else {
      importInsStaffToList();
    }
    queryClient.invalidateQueries({
      queryKey: ['insuranceOrderServices/getInsuranceOrderListByOrderRelevance'],
    });
    getList();
  } catch (error) {}
}
const { dialogProps, handleAdd } = useFormDialog({
  defaultFormParams: {
    id: '',
    materialName: '',
    url: [] as UploadUserFile[],
  },
});
async function importInsStaffToList() {
  try {
    let params: API.APIimportInsStaffToListParams = {
      serialNum: editForm.serialNum,
      url: editForm.url?.[0]?.path,
      productIdNumber: editForm.productIdNumber,
      productSchemeIdNumber: editForm.productSchemeIdNumber,
    };
    let res = await insuranceOrderServices.importInsStaffToList(params);
    if (res.length > 0) {
      await Message.tipMessage('存在错误数据,是否导出?');
      XLSXUtils.exportToXLSX({
        workbookDataList: res,
        fileName: '错误人员名单',
        workbookHeaderMap: {
          name: '雇员姓名',
          sex: '性别',
          certType: '证件类型',
          certNo: '证件号码',
          jobName: '雇员工种',
          useEmploer: '用工单位',
          address: '用工地点',
          note: '备注',
        },
      });
    }
    dialogState.dialogVisible = false;
    getList(paginationState.pageIndex);
  } catch (error) {}
}
function openDialog(row: API.InsuranceOrderListOutput) {
const { dialogProps: dialogInstructionsProps, dialogState: dialogInstructionsState } = useDialog();
function handleOpenInstructions() {
  dialogInstructionsState.dialogVisible = true;
}
function handleUpload() {
  handleAdd({
    id: row.id,
    serialNum: `${dayjs().format('YYYYMMDD')}${_.random(0, 9999).toString().padStart(4, '0')}`,
    url: [] as UploadUserFile[],
  });
}
const router = useRouter();
function goDetail(row: API.InsuranceOrderListOutput) {
  router.push({
    name: 'InsuranceClaimDetail',
    params: {
      id: row.id,
    },
  });
}
async function handleExport() {
async function getInsurancePageExport() {
  try {
    if (paginationState.total === 0) {
      Message.warnMessage('没有数据可以导出哦~');
      return;
    }
    let params = createParams(paginationState.pageIndex, paginationState.pageSize);
    let res = await insuranceOrderServices.exportInsuranceOrderList(params, {
    let res = await insuranceOrderServices.getInsurancePageExport(params, {
      responseType: 'blob',
      getResponse: true,
    });
@@ -308,14 +437,35 @@
  } catch (error) {}
}
function handleDownload() {
  downloadFileByUrl(JYBInsuranceOrderTempPath, '保单导入模板');
async function getInsuranceStaffPageExport() {
  try {
    if (paginationState.total === 0) {
      Message.warnMessage('没有数据可以导出哦~');
      return;
    }
    let params = createParams(paginationState.pageIndex, paginationState.pageSize);
    let res = await insuranceOrderServices.getInsuranceStaffPageExport(params, {
      responseType: 'blob',
      getResponse: true,
    });
    if (res) {
      downloadFile(res.data, `在保人员导出`, 'xlsx');
    }
  } catch (error) {}
}
function handleRowStyle(data: { row: API.InsuranceOrderListOutput; rowIndex: number }) {
function handleDownloadOccupationType() {
  downloadFileByUrl(InsuranceOccupationTypeTempPath, '职业类型对照表');
}
function handleDownload() {
  downloadFileByUrl(InsuranceOrderTempPath, '保单导入模板');
}
function handleRowStyle(data: { row: API.GetInsurancePageOutput }) {
  if (
    dayjs(dayjs(data.row?.insuranceEndTime).format('YYYY-MM-DD')).diff(dayjs(), 'day') >= 0 &&
    dayjs(dayjs(data.row?.insuranceEndTime).format('YYYY-MM-DD')).diff(dayjs(), 'day') < 6
    dayjs(dayjs(data.row?.effectEndTime).format('YYYY-MM-DD')).diff(dayjs(), 'day') >= 0 &&
    dayjs(dayjs(data.row?.effectEndTime).format('YYYY-MM-DD')).diff(dayjs(), 'day') < 6
  ) {
    return {
      color: '#ff0000',
@@ -323,72 +473,124 @@
  }
}
const proTable = ref<InstanceType<typeof ProTableV2>>();
function handleEnterpriseBatchRefund() {
  if (proTableProps.value.tableData.length) {
    const res: API.InsuranceOrderListOutput[] = proTable.value.innerTableRef.getSelectionRows();
    if (res.length > 0) {
      const orderNos = _.uniq(res.map((x) => x.orderNo));
      if (orderNos.length > 1) {
        Message.errorMessage('存在不同的保单号,无法批量减员');
        return;
      }
      handleBatchDownsizing(res);
    } else {
      Message.errorMessage('请先勾选减员人员');
    }
  } else {
    Message.errorMessage('暂无数据');
  }
}
const {
  dialogProps: dialogBatchDownsizingProps,
  handleAdd: handleBatchDownsizingAdd,
  editForm: batchDownsizingForm,
  dialogProps: dialogStampFileProps,
  handleEdit: handleStampFileEdit,
  editForm: stampFileForm,
} = useFormDialog({
  onConfirm: downsizingInsuranceOrderData,
  onConfirm: uploadInsuranceStampFiles,
  defaultFormParams: {
    orderNo: '',
    checkOrderNo: '',
    id: '',
    url: [] as UploadUserFile[],
    downsizingInsuranceList: [] as string[],
  },
});
function handleBatchDownsizing(res: API.InsuranceOrderListOutput[]) {
  handleBatchDownsizingAdd({
    checkOrderNo: res[0]?.orderNo,
    downsizingInsuranceList: res.map((x) => x.id),
  });
async function handleUploadStampFile(row: API.GetInsurancePageOutput) {
  try {
    const url = await getInsurancePolicyStampFiles(row.id);
    handleStampFileEdit({
      id: row.id,
      url: url.map((x) => convertApi2FormUrl(x)) ?? [],
    });
  } catch (error) {}
}
async function downsizingInsuranceOrderData() {
async function uploadInsuranceStampFiles() {
  try {
    let params: API.DownsizingInsuranceOrderData = {
      orderNo: batchDownsizingForm.checkOrderNo,
      downsizingInsuranceList: batchDownsizingForm.downsizingInsuranceList,
      url: batchDownsizingForm.url?.[0]?.path ?? '',
    let params: API.UploadInsuranceStampFilesInput = {
      insurancePolicyId: stampFileForm.id,
      listFiles: stampFileForm.url?.map((x) => x.path) ?? [],
    };
    let res = await insuranceOrderServices.downsizingInsuranceOrderDataCheck(params);
    let res = await insuranceOrderServices.uploadInsuranceStampFiles(params);
    if (res) {
      let downRes = await insuranceOrderServices.downsizingInsuranceOrderData(params, {
        getResponse: true,
        responseType: 'blob',
      });
      if (downRes?.data?.size) {
        await Message.tipMessage('存在错误数据,是否导出?');
        downloadFile(downRes.data, `错误人员名单`, 'xlsx');
      }
      queryClient.invalidateQueries({
        queryKey: ['insuranceOrderServices/getInsuranceOrderListByOrderRelevance'],
      });
      Message.successMessage('上传成功');
      getList(paginationState.pageIndex);
    }
  } catch (error) {}
}
function handleDownloadOrderNo(row: API.InsuranceOrderListOutput) {
  downloadFileByUrl(setOSSLink(row.orderBillFile));
async function getInsurancePolicyStampFiles(id: string) {
  try {
    return await insuranceOrderServices.getInsurancePolicyStampFiles({ id: id });
  } catch (error) {}
}
function handleDownloadInsureFile(row: API.GetInsurancePageOutput) {
  downloadFileByUrl(setOSSLink(row.insureBillUrl));
}
function handleDetail(row: API.GetInsurancePageOutput) {
  router.push({
    name: 'InsuranceOrderDetail',
    params: {
      id: row.id,
    },
  });
}
function handleBatch(row: API.GetInsurancePageOutput) {
  if (
    dayjs(row.effectEndTime).isBefore(dayjs()) ||
    dayjs(row.effectEndTime).isSame(dayjs(), 'day')
  ) {
    Message.errorMessage('保险今天到期,无法批改');
    return;
  }
  router.push({
    name: 'BatchChange',
    params: {
      id: row.id,
    },
    query: {
      insurerName: row.insurerName ?? '',
      insureBillNo: row.insureBillNo ?? '',
      effectEndTime: row.effectEndTime ?? '',
    },
  });
}
async function handleStandarEndo(row: API.GetInsurancePageOutput) {
  try {
    await Message.deleteMessage('是否申请退保?');
    let params = {
      id: row.id,
    };
    // let res = await userServices.deleteRole(params);
    // if (res) {
    //   Message.successMessage('操作成功');
    //   getList(paginationState.pageIndex);
    // }
  } catch (error) {}
}
async function handleGoStampFiles(row: API.GetInsurancePageOutput) {
  try {
    router.push({
      name: 'InsurancePolicyStampFiles',
      params: {
        id: row.id,
      },
    });
  } catch (error) {}
}
function handlePay(row: API.GetInsurancePageOutput) {
  router.push({
    name: 'InsurePayDetail',
    params: {
      id: row.id,
    },
  });
}
async function handleGoDownloadInvoice(row: API.GetInsurancePageOutput) {
  try {
    await insuranceOrderServices.getInvoiceId({ id: row.id });
    router.push({
      name: 'InsureDownloadInvoice',
      params: {
        id: row.id,
      },
    });
  } catch (error) {}
}
</script>