wupengfei
5 天以前 052a1c6f01420d695cb3c251619249725181ff02
feat: 页面
6个文件已添加
14个文件已修改
1673 ■■■■ 已修改文件
src/components/Table/PortraitTableWithAttachment.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/commonView/DeclareEnterpriseTableView.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/enum.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/fourStreams.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/reward.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/fourStreams.ts 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/MaterialReview/MaterialReviewAudit.vue 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/MaterialReview/MaterialReviewDetail.vue 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/FinancialApproval.vue 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/RewardApplyTradeCheck.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/RewardDeclareDetail.vue 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/RewardGrant.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/RewardGrantRegister.vue 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/components/BatchRegisterDialog.vue 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/components/RegisterGrantDialog.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/components/RewardApplyTradeCheckDialog.vue 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/components/UploadFileDialog.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Reward/constants/columns.ts 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/PortraitTableWithAttachment.vue
@@ -1,4 +1,5 @@
<template>
  <slot name="title"></slot>
  <PortraitTable v-bind="portraitTableProps" :label-width="labelWidth"> </PortraitTable>
  <div class="enclosure-list-title">附件列表</div>
  <ProTableV2
src/components/commonView/DeclareEnterpriseTableView.vue
@@ -11,6 +11,9 @@
        </SearchInput>
      </QueryFilterItem>
    </template>
    <template #btn>
      <slot name="btn"></slot>
    </template>
  </ProTableQueryFilterBar>
  <ProTableV2
    v-bind="proTableProps"
@@ -53,23 +56,12 @@
  };
  openDialog?: (row) => void;
  column?: API.ModuleColumnDto[];
  operationBtns?: OperationBtnType[];
};
const props = withDefaults(defineProps<Props>(), {
  column: () => BaseDeclareEnterpriseTableViewColumns,
});
const operationBtns = defineOperationBtns([
  {
    data: {
      enCode: 'detailBtn',
      name: '详情',
    },
    emits: {
      onClick: (role) => props.openDialog(role),
    },
  },
]);
</script>
<style lang="scss" scoped>
src/constants/enum.ts
@@ -49,3 +49,5 @@
  Warning: 'var(--el-color-warning)',
  Danger: 'var(--el-color-danger)',
};
export const TempFolderPath = 'https://parkmanagement.oss-cn-hangzhou.aliyuncs.com/12333/temp';
src/constants/fourStreams.ts
@@ -1,4 +1,5 @@
import { defineColumns } from '@bole-core/components';
import { TempFolderPath } from './enum';
export enum FourStreamsMaterialFileBusinessTypeEnum {
  /** 园区入驻协议 */
@@ -136,3 +137,5 @@
  return { addRewardApplyStep3Columns };
}
export const BountyBatchApplyTransferTemp = `${TempFolderPath}/%E5%85%A5%E8%B4%A6%E6%A8%A1%E6%9D%BF.xlsx`;
src/constants/reward.ts
@@ -134,7 +134,7 @@
export enum IncomeTypeEnum {
  /**财政拨付 */
  Fiscal = 10,
  /**平台充值 */
  /**平台拨付 */
  Platform = 20,
}
src/hooks/fourStreams.ts
New file
@@ -0,0 +1,175 @@
import { defineColumns, defineOperationBtns, useFormDialog, useTable } from '@bole-core/components';
import { OrderInputType } from '@bole-core/core';
import { useQueryClient } from '@tanstack/vue-query';
import { setOSSLink } from '@/utils';
import {
  CustomerApplyFileTypeListItem,
  EnterpriseApplyFileUtils,
} from '@/components/commonView/utils';
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
import * as enterpriseApplyFileServices from '@/services/api/EnterpriseApplyFile';
import { BaseDeclareEnterpriseTableViewColumns, EnterpriseTypeText } from '@/constants';
export const rewardGrantRegisterColumns = computed(() =>
  defineColumns([
    ...BaseDeclareEnterpriseTableViewColumns,
    {
      id: '9',
      enCode: 'a',
      name: '财政拨付金额',
    },
    {
      id: '10',
      enCode: 'a',
      name: '财政拨付已登记',
    },
    {
      id: '11',
      enCode: 'a',
      name: '最近登记日期',
    },
    {
      id: '12',
      enCode: 'a',
      name: '财政拨付登记状态',
    },
    {
      id: '13',
      enCode: 'a',
      name: '平台拨付金额',
    },
    {
      id: '14',
      enCode: 'a',
      name: '平台拨付已登记',
    },
    {
      id: '15',
      enCode: 'a',
      name: '最近登记日期',
    },
    {
      id: '16',
      enCode: 'a',
      name: '平台拨付登记状态',
    },
  ])
);
type UseDeclareEnterpriseTableOptions = {
  id?: Ref<string>;
  applyMonth?: Ref<string>;
};
export function useDeclareEnterpriseTable(options: UseDeclareEnterpriseTableOptions = {}) {
  const { id, applyMonth } = options;
  const {
    getDataSource: getList,
    proTableProps,
    paginationState,
    extraParamState,
    reset,
  } = useTable(
    async ({ pageIndex, pageSize }, extraParamState) => {
      try {
        let params: API.GetParkBountyApplyInfoInput = {
          pageModel: {
            rows: pageSize,
            page: pageIndex,
            orderInput: extraParamState.orderInput,
          },
          searchKeyWord: extraParamState.searchKeyWord,
          parkBountyApplyId: id.value,
        };
        let res = await parkBountyApplyServices.getOutCheckParkBountyApplyDetailList(params);
        return res;
      } catch (error) {}
    },
    {
      defaultExtraParams: {
        orderInput: [{ property: 'parkBountyApplyId', order: OrderInputType.Desc }],
        searchKeyWord: '',
      },
      columnsRenderProps: {
        authType: { type: 'enum', valueEnum: EnterpriseTypeText },
        licenseUrl: {
          type: 'urlV2',
          formatter: (row: API.UserCertificationAuditListDto) => setOSSLink(row.licenseUrl),
        },
        applyAmount: { type: 'money' },
      },
    }
  );
  const queryClient = useQueryClient();
  const { dialogProps, handleAdd, editForm, dialogState } = useFormDialog({
    defaultFormParams: {
      list: [] as CustomerApplyFileTypeListItem[],
      companyId: '',
    },
  });
  async function openDialog(row: API.ParkBountyApplyDetailInfo) {
    try {
      const applyFilesRes = await queryClient.ensureQueryData({
        queryKey: [
          'enterpriseApplyFileServices/getCustomerUploadApplyFiles',
          row.enterpriseId,
          applyMonth.value,
        ],
        queryFn: async () => {
          return await enterpriseApplyFileServices.getCustomerUploadApplyFiles({
            enterpriseId: row.enterpriseId,
            withMonth: applyMonth.value,
          });
        },
      });
      const lastUploadEnterPactFile = await queryClient.ensureQueryData({
        queryKey: ['enterpriseApplyFileServices/getCustomerUploadApplyFiles', row.enterpriseId],
        queryFn: async () => {
          return await parkBountyApplyServices.getEnterpriseLastUploadEnterPactFileNew({
            companyId: row.enterpriseId,
          });
        },
      });
      const applyUploadFiles = await parkBountyApplyServices.getEnterpriseParkApplyUploadFiles({
        companyId: row.enterpriseId,
        parkBountyApplyId: id.value,
      });
      handleAdd({
        list: EnterpriseApplyFileUtils.initParkCollectFileListApplyFiles(
          applyUploadFiles,
          applyFilesRes.items,
          lastUploadEnterPactFile
        ),
        companyId: row.enterpriseId,
      });
    } catch (error) {}
  }
  const operationBtns = defineOperationBtns([
    {
      data: {
        enCode: 'detailBtn',
        name: '详情',
      },
      emits: {
        onClick: (row) => openDialog(row),
      },
    },
  ]);
  return {
    getList,
    proTableProps,
    paginationState,
    extraParamState,
    reset,
    openDialog,
    dialogProps,
    dialogState,
    editForm,
    operationBtns,
  };
}
src/hooks/index.ts
@@ -9,3 +9,4 @@
export * from './help';
export * from './dic';
export * from './table';
export * from './fourStreams';
src/router/index.ts
@@ -222,13 +222,24 @@
        },
      },
      {
        path: '/RewardGrantRegister/:id',
        name: 'RewardGrantRegister',
        hidden: true,
        component: () => import('@/views/Reward/RewardGrantRegister.vue'),
        meta: {
          rank: 10033,
          title: '奖励金登记',
          rootMenu: false,
        },
      },
      {
        path: '/WithdrawalApproval',
        name: 'WithdrawalApproval',
        hidden: false,
        alwaysShow: true,
        component: () => import('@/views/Reward/WithdrawalApproval.vue'),
        meta: {
          rank: 10033,
          rank: 10040,
          title: '提现审批',
          // rootMenu: true,
          icon: 'home',
@@ -241,12 +252,25 @@
        alwaysShow: true,
        component: () => import('@/views/Reward/RewardApplyTradeCheck.vue'),
        meta: {
          rank: 10034,
          rank: 10050,
          title: '出账审批',
          // rootMenu: true,
          icon: 'home',
        },
      },
      {
        path: '/FinancialApproval',
        name: 'FinancialApproval',
        hidden: false,
        alwaysShow: true,
        component: () => import('@/views/Reward/FinancialApproval.vue'),
        meta: {
          rank: 10060,
          title: '财务审批',
          // rootMenu: true,
          icon: 'home',
        },
      },
    ],
  },
  // {
src/views/MaterialReview/MaterialReviewAudit.vue
@@ -9,7 +9,7 @@
              :extra-param-state="extraParamState"
              :pro-table-props="proTableProps"
              :reset="reset"
              :open-dialog="openDialog"
              :operationBtns="operationBtns"
            ></DeclareEnterpriseTableView>
            <MateriaDetailDialog
              v-bind="dialogProps"
@@ -91,7 +91,7 @@
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
import * as enterpriseApplyFileServices from '@/services/api/EnterpriseApplyFile';
import { convertApi2FormUrlObjectBySeparator, setOSSLink } from '@/utils';
import { useGlobalEventContext, useRouteView } from '@/hooks';
import { useDeclareEnterpriseTable, useGlobalEventContext, useRouteView } from '@/hooks';
import { FormInstance } from 'element-plus';
import { Message, OrderInputType } from '@bole-core/core';
import { FourStreamsMaterialFileTableItem } from '@/components/commonView/types';
@@ -116,17 +116,18 @@
  parkTypeName: '',
  applyMonth: '',
  applySumAmount: 0,
  // enterpriseTaxSubFileUrl: [] as UploadUserFile[],
  // enterpriseOperateFileUrl: [] as UploadUserFile[],
  // enterpriseRelateFileUrl: [] as UploadUserFile[],
  // bountyAssignFileUlr: [] as UploadUserFile[],
  // bountyCollectFileUrl: [] as UploadUserFile[],
  parkCollectFileList: [] as CustomerApplyFileTypeListItem[],
  calculationFileList: [] as CustomerApplyFileTypeListItem[],
  status: '' as any as BountyCheckStatusEnum,
  remark: '',
});
const { extraParamState, getList, reset, proTableProps, operationBtns, dialogProps } =
  useDeclareEnterpriseTable({
    id: ref(id),
    applyMonth: toRef(form, 'applyMonth'),
  });
const { data: detail, isLoading } = useQuery({
  queryKey: ['parkBountyApplyServices/getOutCheckParkBountyApplyDetailBaseInfo', id],
@@ -145,17 +146,6 @@
    form.parkTypeName = data.parkTypeName;
    form.applyMonth = data.applyMonth;
    form.applySumAmount = data.applySumAmount;
    // form.enterpriseTaxSubFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseTaxSubFileUrl
    // );
    // form.enterpriseOperateFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseOperateFileUrl
    // );
    // form.bountyAssignFileUlr = convertApi2FormUrlObjectBySeparator(data?.bountyAssignFileUlr);
    // form.bountyCollectFileUrl = convertApi2FormUrlObjectBySeparator(data?.bountyCollectFileUrl);
    // form.enterpriseRelateFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseRelateFileUrl
    // );
    form.parkCollectFileList = EnterpriseApplyFileUtils.convertApiFileToParkCollectFileList(
      data.listFiles
    );
@@ -166,43 +156,6 @@
    getList();
  },
});
const {
  getDataSource: getList,
  proTableProps,
  paginationState,
  extraParamState,
  reset,
} = useTable(
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params: API.GetParkBountyApplyInfoInput = {
        pageModel: {
          rows: pageSize,
          page: pageIndex,
          orderInput: extraParamState.orderInput,
        },
        searchKeyWord: extraParamState.searchKeyWord,
        parkBountyApplyId: id,
      };
      let res = await parkBountyApplyServices.getOutCheckParkBountyApplyDetailList(params);
      return res;
    } catch (error) {}
  },
  {
    defaultExtraParams: {
      orderInput: [{ property: 'enterpriseId', order: OrderInputType.Desc }],
      searchKeyWord: '',
    },
    columnsRenderProps: {
      authType: { type: 'enum', valueEnum: EnterpriseTypeText },
      licenseUrl: {
        type: 'urlV2',
        formatter: (row: API.UserCertificationAuditListDto) => setOSSLink(row.licenseUrl),
      },
    },
  }
);
function handleBack() {
  closeViewPush(route, {
@@ -242,52 +195,7 @@
  } catch (error) {}
}
const { dialogProps, handleAdd, editForm } = useFormDialog({
  defaultFormParams: {
    list: [] as CustomerApplyFileTypeListItem[],
    companyId: '',
  },
});
const { getIndustrialParkTypeNameById } = useIndustrialParkDropDownList();
async function openDialog(row: API.ParkBountyApplyDetailInfo) {
  try {
    const applyFilesRes = await queryClient.ensureQueryData({
      queryKey: [
        'enterpriseApplyFileServices/getCustomerUploadApplyFiles',
        row.enterpriseId,
        form.applyMonth,
      ],
      queryFn: async () => {
        return await enterpriseApplyFileServices.getCustomerUploadApplyFiles({
          enterpriseId: row.enterpriseId,
          withMonth: form.applyMonth,
        });
      },
    });
    const lastUploadEnterPactFile = await queryClient.ensureQueryData({
      queryKey: ['enterpriseApplyFileServices/getCustomerUploadApplyFiles', row.enterpriseId],
      queryFn: async () => {
        return await parkBountyApplyServices.getEnterpriseLastUploadEnterPactFileNew({
          companyId: row.enterpriseId,
        });
      },
    });
    const applyUploadFiles = await parkBountyApplyServices.getEnterpriseParkApplyUploadFiles({
      companyId: row.enterpriseId,
      parkBountyApplyId: id,
    });
    handleAdd({
      list: EnterpriseApplyFileUtils.initParkCollectFileListApplyFiles(
        applyUploadFiles,
        applyFilesRes.items,
        lastUploadEnterPactFile
      ),
      companyId: row.enterpriseId,
    });
  } catch (error) {}
}
</script>
<style lang="scss" scoped>
src/views/MaterialReview/MaterialReviewDetail.vue
@@ -24,8 +24,8 @@
              :extra-param-state="extraParamState"
              :pro-table-props="proTableProps"
              :reset="reset"
              :open-dialog="openDialog"
              :column="addRewardApplyStep3Columns"
              :operationBtns="operationBtns"
            ></DeclareEnterpriseTableView>
            <MateriaDetailDialog
              v-bind="dialogProps"
@@ -47,34 +47,25 @@
import {
  AppContainer,
  LoadingLayout,
  UploadUserFile,
  PageFormLayout,
  useTable,
  useFormDialog,
  TextOverTooltip,
} from '@bole-core/components';
import ChunkCellV2 from '@/components/Layout/ChunkCellV2.vue';
import DetailView from '@/components/commonView/DetailView.vue';
import MateriaDetailDialog from '@/components/commonView/MateriaDetailDialog.vue';
import DeclareEnterpriseTableView from '@/components/commonView/DeclareEnterpriseTableView.vue';
import { useQuery, useQueryClient } from '@tanstack/vue-query';
import { useQuery } from '@tanstack/vue-query';
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
import * as enterpriseApplyFileServices from '@/services/api/EnterpriseApplyFile';
import { convertApi2FormUrlObjectBySeparator, setOSSLink } from '@/utils';
import { useRouteView } from '@/hooks';
import { OrderInputType } from '@bole-core/core';
import { useDeclareEnterpriseTable, useRouteView } from '@/hooks';
import {
  EnterpriseTypeText,
  BountyCheckStatusEnum,
  BountyCheckStatusEnumText,
  BountyCheckStatusEnumColor,
  useAddRewardApplyStep3Columns,
} from '@/constants';
import { FourStreamsMaterialFileTableItem } from '@/components/commonView/types';
import {
  CustomerApplyFileTypeListItem,
  EnterpriseApplyFileUtils,
  FourStreamsMaterialUtils,
} from '@/components/commonView/utils';
import { useIndustrialParkDropDownList } from '@/hooks/industrialPark';
@@ -91,11 +82,6 @@
  parkTypeName: '',
  applyMonth: '',
  applySumAmount: 0,
  // enterpriseTaxSubFileUrl: [] as UploadUserFile[],
  // enterpriseOperateFileUrl: [] as UploadUserFile[],
  // enterpriseRelateFileUrl: [] as UploadUserFile[],
  // bountyAssignFileUlr: [] as UploadUserFile[],
  // bountyCollectFileUrl: [] as UploadUserFile[],
  parkCollectFileList: [] as CustomerApplyFileTypeListItem[],
  calculationFileList: [] as CustomerApplyFileTypeListItem[],
@@ -108,6 +94,12 @@
const { addRewardApplyStep3Columns } = useAddRewardApplyStep3Columns({
  suportEnterpriseUpload: toRef(form, 'suportEnterpriseUpload'),
});
const { extraParamState, getList, reset, proTableProps, operationBtns, dialogProps } =
  useDeclareEnterpriseTable({
    id: ref(id),
    applyMonth: toRef(form, 'applyMonth'),
  });
const tableRef = ref<InstanceType<typeof DeclareEnterpriseTableView>>();
@@ -130,17 +122,6 @@
    form.applySumAmount = data.applySumAmount;
    form.outCheckStatus = data.outCheckStatus;
    form.outCheckRemark = data.outCheckRemark;
    // form.enterpriseTaxSubFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseTaxSubFileUrl
    // );
    // form.enterpriseOperateFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseOperateFileUrl
    // );
    // form.bountyAssignFileUlr = convertApi2FormUrlObjectBySeparator(data?.bountyAssignFileUlr);
    // form.bountyCollectFileUrl = convertApi2FormUrlObjectBySeparator(data?.bountyCollectFileUrl);
    // form.enterpriseRelateFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseRelateFileUrl
    // );
    form.parkCollectFileList = EnterpriseApplyFileUtils.convertApiFileToParkCollectFileList(
      data.listFiles
    );
@@ -154,94 +135,7 @@
  },
});
const {
  getDataSource: getList,
  proTableProps,
  paginationState,
  extraParamState,
  reset,
} = useTable(
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params: API.GetParkBountyApplyInfoInput = {
        pageModel: {
          rows: pageSize,
          page: pageIndex,
          orderInput: extraParamState.orderInput,
        },
        searchKeyWord: extraParamState.searchKeyWord,
        parkBountyApplyId: id,
      };
      let res = await parkBountyApplyServices.getOutCheckParkBountyApplyDetailList(params);
      return res;
    } catch (error) {}
  },
  {
    defaultExtraParams: {
      orderInput: [{ property: 'parkBountyApplyId', order: OrderInputType.Desc }],
      searchKeyWord: '',
    },
    columnsRenderProps: {
      authType: { type: 'enum', valueEnum: EnterpriseTypeText },
      applyAmount: { type: 'money' },
    },
  }
);
const { dialogProps, handleAdd, editForm } = useFormDialog({
  defaultFormParams: {
    list: [] as CustomerApplyFileTypeListItem[],
    companyId: '',
  },
});
const { getIndustrialParkTypeNameById } = useIndustrialParkDropDownList();
const queryClient = useQueryClient();
async function openDialog(row: API.ParkBountyApplyDetailInfo) {
  try {
    const applyFilesRes = await queryClient.ensureQueryData({
      queryKey: [
        'enterpriseApplyFileServices/getCustomerUploadApplyFiles',
        row.enterpriseId,
        form.applyMonth,
      ],
      queryFn: async () => {
        return await enterpriseApplyFileServices.getCustomerUploadApplyFiles({
          enterpriseId: row.enterpriseId,
          withMonth: form.applyMonth,
        });
      },
    });
    const lastUploadEnterPactFile = await queryClient.ensureQueryData({
      queryKey: ['enterpriseApplyFileServices/getCustomerUploadApplyFiles', row.enterpriseId],
      queryFn: async () => {
        return await parkBountyApplyServices.getEnterpriseLastUploadEnterPactFileNew({
          companyId: row.enterpriseId,
        });
      },
    });
    const applyUploadFiles = await parkBountyApplyServices.getEnterpriseParkApplyUploadFiles({
      companyId: row.enterpriseId,
      parkBountyApplyId: id,
    });
    handleAdd({
      list: EnterpriseApplyFileUtils.initParkCollectFileListApplyFiles(
        applyUploadFiles,
        applyFilesRes.items,
        lastUploadEnterPactFile
      ),
      companyId: row.enterpriseId,
    });
  } catch (error) {}
  // handleAdd({
  //   list: FourStreamsMaterialUtils.initFourStreamsMaterialFileList(
  //     row,
  //     getIndustrialParkTypeNameById(detail.value?.parkId)
  //   ),
  //   companyId: row.enterpriseId,
  // });
}
function handleBack() {
  closeViewPush(route, {
src/views/Reward/FinancialApproval.vue
New file
@@ -0,0 +1,257 @@
<template>
  <LoadingLayout :loading="state.loading">
    <AppContainer>
      <ProTableQueryFilterBar @on-reset="reset">
        <template #query>
          <QueryFilterItem>
            <FieldSelect
              v-model="extraParamState.enterpriseId"
              placeholder="请选择园区"
              :value-enum="fourStreamsIndustrialParkList"
              enumLabelKey="parkName"
              enum-value-key="id"
              clearable
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem tip-content="审核状态">
            <FieldRadio
              v-model="extraParamState.auditStatus"
              :value-enum="EnumParkBountyTradeDetailAuditStatusText"
              buttonStyle
              showAllBtn
              @change="getList()"
            ></FieldRadio>
          </QueryFilterItem>
          <QueryFilterItem tip-content="申请出账日期">
            <FieldDatePicker
              v-model="extraParamState.creationTime"
              type="daterange"
              range-separator="~"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              clearable
              @change="getList()"
            ></FieldDatePicker>
          </QueryFilterItem>
          <QueryFilterItem>
            <SearchInput
              v-model="extraParamState.searchKeyWord"
              style="width: 200px"
              placeholder="企业名称/信用代码"
              @on-click-search="getList"
            >
            </SearchInput>
          </QueryFilterItem>
        </template>
      </ProTableQueryFilterBar>
      <ProTableV2
        v-bind="proTableProps"
        :columns="RewardApplyTradeCheckColumns"
        :operationBtns="operationBtns"
      >
      </ProTableV2>
      <RewardApplyTradeCheckDialog v-bind="dialogProps"></RewardApplyTradeCheckDialog>
    </AppContainer>
  </LoadingLayout>
</template>
<script setup lang="ts">
import {
  ProTableQueryFilterBar,
  FieldSelect,
  ProTableV2,
  SearchInput,
  LoadingLayout,
  AppContainer,
  QueryFilterItem,
  useTable,
  FieldDatePicker,
  useFormDialog,
  UploadUserFile,
  defineOperationBtns,
  FieldRadio,
} from '@bole-core/components';
import { Message, OrderInputType } from '@bole-core/core';
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
import {
  EnterpriseType,
  EnterpriseTypeText,
  EnumParkBountyTradeDetailAuditStatus,
  EnumParkBountyTradeDetailAuditStatusTag,
  EnumParkBountyTradeDetailAuditStatusText,
} from '@/constants';
import { ModelValueType } from 'element-plus';
import RewardApplyTradeCheckDialog from './components/RewardApplyTradeCheckDialog.vue';
import { convertApi2FormUrlOnlyOne, format } from '@/utils';
import { RewardApplyTradeCheckColumns } from './constants';
import { useIndustrialParkDropDownList } from '@/hooks/industrialPark';
defineOptions({
  name: 'FinancialApproval',
});
const operationBtns = defineOperationBtns([
  {
    data: {
      enCode: 'detailBtn',
      name: '详情',
    },
    emits: {
      onClick: (role) => openDialog(role, true),
    },
    extraProps: {
      hide: (row: API.GetParkBountyTradeDetailOutput) =>
        row.auditStatus === EnumParkBountyTradeDetailAuditStatus.Wait,
    },
  },
  {
    data: {
      enCode: 'checkBtn',
      name: '审批',
    },
    emits: {
      onClick: (row) => openDialog(row),
    },
    extraProps: {
      hide: (row: API.GetParkBountyTradeDetailOutput) =>
        row.auditStatus !== EnumParkBountyTradeDetailAuditStatus.Wait,
    },
  },
]);
const BaseState = {
  loading: true,
};
const state = reactive({ ...BaseState });
const { industrialParkList } = useIndustrialParkDropDownList();
const fourStreamsIndustrialParkList = computed(() => {
  return industrialParkList.value.filter((x) => !!x.rewardEnable);
});
onMounted(async () => {
  await getList();
  state.loading = false;
});
const {
  getDataSource: getList,
  proTableProps,
  paginationState,
  extraParamState,
  reset,
} = useTable(
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params: API.GetParkBountyTradeDetailByIdInput = {
        pageModel: {
          rows: pageSize,
          page: pageIndex,
          orderInput: extraParamState.orderInput,
        },
        searchKeyWord: extraParamState.searchKeyWord,
        // transferTimeBegin: format(extraParamState.transferTime?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
        // transferTimeEnd: format(extraParamState.transferTime?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
        creationTimeBegin: format(extraParamState.creationTime?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
        creationTimeEnd: format(extraParamState.creationTime?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
        // "enterpriseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        // "auditStatus": 10
      };
      let res = await parkBountyApplyServices.getParkBountyTradeDetailList(params, {
        showLoading: !state.loading,
      });
      return res;
    } catch (error) {}
  },
  {
    defaultExtraParams: {
      searchKeyWord: '',
      enterpriseId: '',
      auditStatus: '' as any as EnumParkBountyTradeDetailAuditStatus,
      creationTime: [] as unknown as ModelValueType,
      orderInput: [{ property: 'tradeTime', order: OrderInputType.Desc }],
    },
    columnsRenderProps: {
      authType: { type: 'enum', valueEnum: EnterpriseTypeText },
      tradeTime: { type: 'date', format: 'YYYY-MM-DD HH:mm:ss' },
      tradeAmount: { type: 'money' },
      remianAmount: { type: 'money' },
      auditStatus: {
        type: 'tag',
        valueEnum: EnumParkBountyTradeDetailAuditStatusText,
        tagTypeEnum: EnumParkBountyTradeDetailAuditStatusTag,
      },
    },
  }
);
function openDialog(row: API.GetParkBountyTradeDetailOutput, isCheck = false) {
  handleAdd({
    id: row.id,
    isCheck,
    auditStatus:
      row.auditStatus === EnumParkBountyTradeDetailAuditStatus.Reject
        ? EnumParkBountyTradeDetailAuditStatus.Reject
        : EnumParkBountyTradeDetailAuditStatus.Pass,
    auditRemark: row.auditRemark,
    payAuditFileUrl: convertApi2FormUrlOnlyOne(row.payAuditFileUrl),
    userName: row.userName,
    enterpriseName: row.enterpriseName,
    societyCreditCode: row.societyCreditCode,
    contactPhone: row.contactPhone,
    authType: row.authType,
    parkName: row.parkName,
    parkTypeName: row.parkTypeName,
    tradeAmount: row.tradeAmount,
    remianAmount: row.remianAmount,
    tradeTime: row.tradeTime,
    auditTime: row.auditTime,
    payRemark: row.payRemark,
    payFileUrl: convertApi2FormUrlOnlyOne(row.payFileUrl),
  });
}
const { dialogProps, handleAdd, handleEdit, editForm } = useFormDialog({
  onConfirm: handleAddOrEdit,
  defaultFormParams: {
    id: '',
    auditStatus: '' as any as EnumParkBountyTradeDetailAuditStatus,
    auditRemark: '',
    payAuditFileUrl: [] as UploadUserFile[],
    isCheck: false,
    userName: '',
    enterpriseName: '',
    societyCreditCode: '',
    contactPhone: '',
    authType: EnterpriseType.HREnterprise,
    parkName: '',
    parkTypeName: '',
    tradeAmount: '' as any as number,
    remianAmount: '' as any as number,
    tradeTime: '',
    auditTime: '',
    payRemark: '',
    payFileUrl: [] as UploadUserFile[],
  },
});
async function handleAddOrEdit() {
  try {
    let params: API.AuditParkBountyTradeInput = {
      id: editForm.id,
      auditStatus: editForm.auditStatus,
      /** 审核备注 */
      auditRemark: editForm.auditRemark,
      /** 审核凭证 */
      payAuditFileUrl: editForm.payAuditFileUrl?.[0]?.path ?? '',
    };
    let res = await parkBountyApplyServices.auditParkBountyApplyTrade(params);
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
    }
  } catch (error) {}
}
</script>
src/views/Reward/RewardApplyTradeCheck.vue
@@ -3,6 +3,26 @@
    <AppContainer>
      <ProTableQueryFilterBar @on-reset="reset">
        <template #query>
          <QueryFilterItem>
            <FieldSelect
              v-model="extraParamState.enterpriseId"
              placeholder="请选择园区"
              :value-enum="fourStreamsIndustrialParkList"
              enumLabelKey="parkName"
              enum-value-key="id"
              clearable
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem tip-content="审核状态">
            <FieldRadio
              v-model="extraParamState.auditStatus"
              :value-enum="EnumParkBountyTradeDetailAuditStatusText"
              buttonStyle
              showAllBtn
              @change="getList()"
            ></FieldRadio>
          </QueryFilterItem>
          <QueryFilterItem tip-content="申请出账日期">
            <FieldDatePicker
              v-model="extraParamState.creationTime"
@@ -39,7 +59,7 @@
<script setup lang="ts">
import {
  ProTableQueryFilterBar,
  OperationBtnType,
  FieldSelect,
  ProTableV2,
  SearchInput,
  LoadingLayout,
@@ -50,6 +70,7 @@
  useFormDialog,
  UploadUserFile,
  defineOperationBtns,
  FieldRadio,
} from '@bole-core/components';
import { Message, OrderInputType } from '@bole-core/core';
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
@@ -64,6 +85,7 @@
import RewardApplyTradeCheckDialog from './components/RewardApplyTradeCheckDialog.vue';
import { convertApi2FormUrlOnlyOne, format } from '@/utils';
import { RewardApplyTradeCheckColumns } from './constants';
import { useIndustrialParkDropDownList } from '@/hooks/industrialPark';
defineOptions({
  name: 'RewardApplyTradeCheck',
@@ -103,6 +125,11 @@
};
const state = reactive({ ...BaseState });
const { industrialParkList } = useIndustrialParkDropDownList();
const fourStreamsIndustrialParkList = computed(() => {
  return industrialParkList.value.filter((x) => !!x.rewardEnable);
});
onMounted(async () => {
  await getList();
@@ -141,6 +168,8 @@
  {
    defaultExtraParams: {
      searchKeyWord: '',
      enterpriseId: '',
      auditStatus: '' as any as EnumParkBountyTradeDetailAuditStatus,
      creationTime: [] as unknown as ModelValueType,
      orderInput: [{ property: 'tradeTime', order: OrderInputType.Desc }],
    },
src/views/Reward/RewardDeclareDetail.vue
@@ -9,8 +9,8 @@
              :extra-param-state="extraParamState"
              :pro-table-props="proTableProps"
              :reset="reset"
              :open-dialog="openDialog"
              :column="addRewardApplyStep3Columns"
              :operationBtns="operationBtns"
            ></DeclareEnterpriseTableView>
            <MateriaDetailDialog
              v-bind="dialogProps"
@@ -29,31 +29,19 @@
</template>
<script setup lang="ts">
import {
  AppContainer,
  LoadingLayout,
  UploadUserFile,
  PageFormLayout,
  useTable,
  useFormDialog,
} from '@bole-core/components';
import { AppContainer, LoadingLayout, PageFormLayout } from '@bole-core/components';
import DetailView from '@/components/commonView/DetailView.vue';
import ChunkCellV2 from '@/components/Layout/ChunkCellV2.vue';
import MateriaDetailDialog from '@/components/commonView/MateriaDetailDialog.vue';
import DeclareEnterpriseTableView from '@/components/commonView/DeclareEnterpriseTableView.vue';
import { useQuery, useQueryClient } from '@tanstack/vue-query';
import { useQuery } from '@tanstack/vue-query';
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
import * as enterpriseApplyFileServices from '@/services/api/EnterpriseApplyFile';
import { convertApi2FormUrlObjectBySeparator, setOSSLink } from '@/utils';
import { useRouteView } from '@/hooks';
import { OrderInputType } from '@bole-core/core';
import { EnterpriseTypeText, useAddRewardApplyStep3Columns } from '@/constants';
import { FourStreamsMaterialFileTableItem } from '@/components/commonView/types';
import { useDeclareEnterpriseTable, useRouteView } from '@/hooks';
import { useAddRewardApplyStep3Columns } from '@/constants';
import { useIndustrialParkDropDownList } from '@/hooks/industrialPark';
import {
  CustomerApplyFileTypeListItem,
  EnterpriseApplyFileUtils,
  FourStreamsMaterialUtils,
} from '@/components/commonView/utils';
defineOptions({
@@ -69,19 +57,20 @@
  parkTypeName: '',
  applyMonth: '',
  applySumAmount: 0,
  // enterpriseTaxSubFileUrl: [] as UploadUserFile[],
  // enterpriseOperateFileUrl: [] as UploadUserFile[],
  // enterpriseRelateFileUrl: [] as UploadUserFile[],
  parkCollectFileList: [] as CustomerApplyFileTypeListItem[],
  calculationFileList: [] as CustomerApplyFileTypeListItem[],
  // bountyAssignFileUlr: [] as UploadUserFile[],
  // bountyCollectFileUrl: [] as UploadUserFile[],
  suportEnterpriseUpload: false,
});
const { addRewardApplyStep3Columns } = useAddRewardApplyStep3Columns({
  suportEnterpriseUpload: toRef(form, 'suportEnterpriseUpload'),
});
const { extraParamState, getList, reset, proTableProps, operationBtns, dialogProps } =
  useDeclareEnterpriseTable({
    id: ref(id),
    applyMonth: toRef(form, 'applyMonth'),
  });
const { data: detail, isLoading } = useQuery({
  queryKey: ['parkBountyApplyServices/getParkBountyApplyDetailBaseInfo', id],
@@ -100,121 +89,19 @@
    form.parkTypeName = data.parkTypeName;
    form.applyMonth = data.applyMonth;
    form.applySumAmount = data.applySumAmount;
    // form.enterpriseTaxSubFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseTaxSubFileUrl
    // );
    // form.enterpriseOperateFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseOperateFileUrl
    // );
    form.parkCollectFileList = EnterpriseApplyFileUtils.convertApiFileToParkCollectFileList(
      data.listFiles
    );
    form.calculationFileList = EnterpriseApplyFileUtils.convertApiFileToParkCollectFileList(
      data.collectCountListFiles
    );
    // form.bountyAssignFileUlr = convertApi2FormUrlObjectBySeparator(data?.bountyAssignFileUlr);
    // form.bountyCollectFileUrl = convertApi2FormUrlObjectBySeparator(data?.bountyCollectFileUrl);
    // form.enterpriseRelateFileUrl = convertApi2FormUrlObjectBySeparator(
    //   data?.enterpriseRelateFileUrl
    // );
    form.suportEnterpriseUpload = data.suportEnterpriseUpload;
    getList();
  },
});
const {
  getDataSource: getList,
  proTableProps,
  paginationState,
  extraParamState,
  reset,
} = useTable(
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params: API.GetParkBountyApplyInfoInput = {
        pageModel: {
          rows: pageSize,
          page: pageIndex,
          orderInput: extraParamState.orderInput,
        },
        searchKeyWord: extraParamState.searchKeyWord,
        parkBountyApplyId: id,
      };
      let res = await parkBountyApplyServices.getOutCheckParkBountyApplyDetailList(params);
      return res;
    } catch (error) {}
  },
  {
    defaultExtraParams: {
      orderInput: [{ property: 'parkBountyApplyId', order: OrderInputType.Desc }],
      searchKeyWord: '',
    },
    columnsRenderProps: {
      authType: { type: 'enum', valueEnum: EnterpriseTypeText },
      licenseUrl: {
        type: 'urlV2',
        formatter: (row: API.UserCertificationAuditListDto) => setOSSLink(row.licenseUrl),
      },
      applyAmount: { type: 'money' },
    },
  }
);
const { dialogProps, handleAdd, editForm } = useFormDialog({
  defaultFormParams: {
    list: [] as CustomerApplyFileTypeListItem[],
    companyId: '',
  },
});
const { getIndustrialParkTypeNameById } = useIndustrialParkDropDownList();
const queryClient = useQueryClient();
async function openDialog(row: API.ParkBountyApplyDetailInfo) {
  try {
    const applyFilesRes = await queryClient.ensureQueryData({
      queryKey: [
        'enterpriseApplyFileServices/getCustomerUploadApplyFiles',
        row.enterpriseId,
        form.applyMonth,
      ],
      queryFn: async () => {
        return await enterpriseApplyFileServices.getCustomerUploadApplyFiles({
          enterpriseId: row.enterpriseId,
          withMonth: form.applyMonth,
        });
      },
    });
    const lastUploadEnterPactFile = await queryClient.ensureQueryData({
      queryKey: ['enterpriseApplyFileServices/getCustomerUploadApplyFiles', row.enterpriseId],
      queryFn: async () => {
        return await parkBountyApplyServices.getEnterpriseLastUploadEnterPactFileNew({
          companyId: row.enterpriseId,
        });
      },
    });
    const applyUploadFiles = await parkBountyApplyServices.getEnterpriseParkApplyUploadFiles({
      companyId: row.enterpriseId,
      parkBountyApplyId: id,
    });
    handleAdd({
      list: EnterpriseApplyFileUtils.initParkCollectFileListApplyFiles(
        applyUploadFiles,
        applyFilesRes.items,
        lastUploadEnterPactFile
      ),
      companyId: row.enterpriseId,
    });
  } catch (error) {}
  // handleEdit({
  //   list: FourStreamsMaterialUtils.initFourStreamsMaterialFileList(
  //     row,
  //     getIndustrialParkTypeNameById(detail.value?.parkId)
  //   ),
  //   companyId: row.enterpriseId,
  // });
}
function handleBack() {
  closeViewPush(route, {
src/views/Reward/RewardGrant.vue
@@ -233,7 +233,7 @@
      name: '登记',
    },
    emits: {
      onClick: (role) => openRegisterDialog(role),
      onClick: (role) => goRewardGrantRegister(role),
    },
    extraProps: {
      hide: (row: API.GetParkBountyApplyListOutput) =>
@@ -544,6 +544,15 @@
    }
  } catch (error) {}
}
function goRewardGrantRegister(row: API.GetParkBountyApplyListOutput) {
  router.push({
    name: 'RewardGrantRegister',
    params: {
      id: row.id,
    },
  });
}
</script>
<style lang="scss" scoped>
src/views/Reward/RewardGrantRegister.vue
New file
@@ -0,0 +1,282 @@
<template>
  <LoadingLayout>
    <AppContainer>
      <PageFormLayout title="奖励金登记">
        <DetailView :form="form">
          <ChunkCellV2 title="申报企业名单">
            <DeclareEnterpriseTableView
              :getList="getList"
              :extra-param-state="extraParamState"
              :pro-table-props="proTableProps"
              :reset="reset"
              :operationBtns="registerOperationBtns"
              :column="rewardGrantRegisterColumns"
            >
              <template #btn>
                <el-button type="primary" link @click="downloadTemp()">下载模板</el-button>
                <el-button icon="Upload" type="primary" @click="openUploadFileDialog()"
                  >导入</el-button
                >
                <el-button icon="Plus" type="primary" @click="openBatchRegisterDialog()"
                  >批量登记</el-button
                >
              </template>
            </DeclareEnterpriseTableView>
            <FourStreamsMaterialFileDialogV2
              v-bind="dialogMaterialFileProps"
              :show-upload-btn="false"
              :show-delete-btn="false"
              :show-check-btn="false"
              downloadBtnText="查看"
              title="查看凭证"
              :BusinessTypeEnumText="TransferFileEnumInRewardGrandText"
            />
          </ChunkCellV2>
        </DetailView>
        <template #footer>
          <el-button @click="handleBack">取消</el-button>
          <el-button @click="handleBack" type="primary">确认</el-button>
        </template>
      </PageFormLayout>
    </AppContainer>
    <RegisterGrantDialog v-bind="dialogRegisterGrantProps" />
    <UploadFileDialog v-bind="dialogUploadFileProps" />
    <BatchRegisterDialog v-bind="dialogBatchRegisterProps" />
  </LoadingLayout>
</template>
<script setup lang="ts">
import {
  AppContainer,
  defineOperationBtns,
  LoadingLayout,
  PageFormLayout,
  UploadUserFile,
  useFormDialog,
  XLSXUtils,
} from '@bole-core/components';
import DetailView from '@/components/commonView/DetailView.vue';
import ChunkCellV2 from '@/components/Layout/ChunkCellV2.vue';
import DeclareEnterpriseTableView from '@/components/commonView/DeclareEnterpriseTableView.vue';
import { useQuery } from '@tanstack/vue-query';
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
import { useRouteView } from '@/hooks';
import { useIndustrialParkDropDownList } from '@/hooks/industrialPark';
import {
  CustomerApplyFileTypeListItem,
  EnterpriseApplyFileUtils,
  FourStreamsMaterialUtils,
} from '@/components/commonView/utils';
import {
  BountyBatchApplyTransferTemp,
  FinanceStatusEnum,
  IncomeTypeEnum,
  SettleStatusEnum,
  TransferFileEnumInRewardGrandText,
} from '@/constants';
import { useDeclareEnterpriseTable, rewardGrantRegisterColumns } from '@/hooks';
import { TransferFileEnumInRewardGrandTableItem } from '@/components/commonView/types';
import RegisterGrantDialog from './components/RegisterGrantDialog.vue';
import BatchRegisterDialog from './components/BatchRegisterDialog.vue';
import UploadFileDialog from './components/UploadFileDialog.vue';
import { downloadFileByUrl } from '@/utils';
import { Message } from '@bole-core/core';
import { ImportParkBountyDataHeaderMap } from './constants';
defineOptions({
  name: 'RewardGrantRegister',
});
const route = useRoute();
const { closeViewPush } = useRouteView();
const id = route.params?.id as string;
const form = reactive({
  batchNo: '',
  parkName: '',
  parkTypeName: '',
  applyMonth: '',
  applySumAmount: 0,
  parkCollectFileList: [] as CustomerApplyFileTypeListItem[],
  calculationFileList: [] as CustomerApplyFileTypeListItem[],
  suportEnterpriseUpload: false,
});
const { extraParamState, paginationState, getList, reset, proTableProps } =
  useDeclareEnterpriseTable({
    id: ref(id),
    applyMonth: toRef(form, 'applyMonth'),
  });
const registerOperationBtns = defineOperationBtns([
  {
    data: {
      enCode: 'registerGrantBtn',
      name: '登记',
    },
    emits: {
      onClick: (row) => openRegisterGrantDialog(row),
    },
  },
  {
    data: {
      enCode: 'checkBtn',
      name: '查看凭证',
    },
    emits: {
      onClick: (row) => openMaterialFileDialog(row),
    },
  },
]);
const { data: detail, isLoading } = useQuery({
  queryKey: ['parkBountyApplyServices/getParkBountyApplyDetailBaseInfo', id],
  queryFn: async () => {
    return await parkBountyApplyServices.getParkBountyApplyDetailBaseInfo(
      { parkBountyApplyId: id },
      {
        showLoading: false,
      }
    );
  },
  placeholderData: () => ({} as API.ParkBountyApplyBaseInfo),
  onSuccess(data) {
    form.batchNo = data.batchNo;
    form.parkName = data.parkName;
    form.parkTypeName = data.parkTypeName;
    form.applyMonth = data.applyMonth;
    form.applySumAmount = data.applySumAmount;
    form.parkCollectFileList = EnterpriseApplyFileUtils.convertApiFileToParkCollectFileList(
      data.listFiles
    );
    form.calculationFileList = EnterpriseApplyFileUtils.convertApiFileToParkCollectFileList(
      data.collectCountListFiles
    );
    form.suportEnterpriseUpload = data.suportEnterpriseUpload;
    getList();
  },
});
const { getIndustrialParkTypeNameById } = useIndustrialParkDropDownList();
const { dialogProps: dialogMaterialFileProps, handleAdd: handleMaterialFileAdd } = useFormDialog({
  defaultFormParams: {
    list: [] as TransferFileEnumInRewardGrandTableItem[],
  },
});
function openMaterialFileDialog(row: API.GetParkBountyApplyListOutput) {
  handleMaterialFileAdd({
    list: FourStreamsMaterialUtils.initApplyRewardGrandFileList(row),
  });
}
const {
  dialogProps: dialogRegisterGrantProps,
  handleEdit: handleRegisterGrantEdit,
  editForm: editRegisterForm,
} = useFormDialog({
  onConfirm: handleRegisterGrant,
  defaultFormParams: {
    incomeType: '' as any as IncomeTypeEnum,
    parkBountyApplyId: '',
    fileUrl: [] as UploadUserFile[],
    financeSumAmount: 0,
    showSuportPlatRecharge: false,
    showSuportFiscalRecharge: false,
  },
});
function openRegisterGrantDialog(row?: API.GetParkBountyApplyListOutput) {
  handleRegisterGrantEdit({
    incomeType: '' as any as IncomeTypeEnum,
    fileUrl: [] as UploadUserFile[],
    showSuportPlatRecharge: row.settleStatus === SettleStatusEnum.WaitForSettle,
    showSuportFiscalRecharge: row.financeStatus === FinanceStatusEnum.WaitForIncome,
    parkBountyApplyId: row.id,
    financeSumAmount: 0,
  });
}
async function handleRegisterGrant() {}
const { dialogProps: dialogUploadFileProps, handleAdd: handleUploadFileAdd } = useFormDialog({
  onConfirm: handleImportParkBountyData,
  defaultFormParams: {
    parkBountyApplyId: '',
    url: [] as UploadUserFile[],
    certificateUrl: [] as UploadUserFile[],
  },
});
async function handleImportParkBountyData(response: UploadUserFile) {
  try {
    let params: API.ImportBountyApplyDataInput = {
      parkBountyApplyId: id,
      url: response.url,
    };
    let res = await parkBountyApplyServices.importParkBountyData(params, {
      timeout: 100000000,
    });
    if (res.error.length > 0) {
      await Message.tipMessage('存在错误数据,是否导出');
      XLSXUtils.exportToXLSX({
        workbookDataList: res.error,
        fileName: '批量导入入账-错误数据',
        workbookHeaderMap: ImportParkBountyDataHeaderMap,
      });
    }
    getList(paginationState.pageIndex);
  } catch (error) {}
}
function openUploadFileDialog() {
  handleUploadFileAdd({
    parkBountyApplyId: id,
    url: [] as UploadUserFile[],
    certificateUrl: [] as UploadUserFile[],
  });
}
async function openBatchRegisterDialog() {
  try {
    handleBatchRegisterAdd({
      parkBountyApplyId: id,
      showSuportPlatRecharge: false,
    });
  } catch (error) {}
}
const {
  dialogProps: dialogBatchRegisterProps,
  handleAdd: handleBatchRegisterAdd,
  editForm: batchRegisterEditForm,
} = useFormDialog({
  onConfirm: handleBatchRegister,
  defaultFormParams: {
    parkBountyApplyDetailIds: [] as string[],
    amount: 0,
    companyList: [] as API.GetNotTransferCompanyNameListOutput[],
    incomeType: IncomeTypeEnum.Fiscal,
    parkBountyApplyId: '',
    showSuportPlatRecharge: false,
    certificateUrl: [] as UploadUserFile[],
  },
});
async function handleBatchRegister() {}
function downloadTemp() {
  downloadFileByUrl(BountyBatchApplyTransferTemp, '登记模板');
}
function handleBack() {
  closeViewPush(route, {
    name: 'RewardGrant',
  });
}
</script>
<style lang="scss" scoped>
@use '@/style/common.scss' as *;
</style>
src/views/Reward/components/BatchRegisterDialog.vue
New file
@@ -0,0 +1,214 @@
<template>
  <ProDialog
    title="批量登记"
    v-model="visible"
    @close="onDialogClose"
    destroy-on-close
    draggable
    width="700px"
  >
    <ProForm :model="form" ref="dialogForm" label-width="120px">
      <ProFormItemV2 prop="ids" class="pro-form-item-label-hidden">
        <div class="batchEntryRewardBody">
          <el-transfer
            v-model="deleteList"
            filterable
            :filter-method="filterMethod"
            filter-placeholder="请输入搜索内容"
            :data="form.companyList"
            :titles="['登记', '不登记']"
            :props="prop"
            @change="handleChange"
          />
        </div>
      </ProFormItemV2>
      <ProFormItemV2 label="登记类型:" prop="incomeType" required>
        <ProFormRadio
          v-model="form.incomeType"
          :value-enum="incomeTypeEnum"
          :button-style="false"
          @change="handleIncomeTypeChange"
        />
      </ProFormItemV2>
      <ProFormItemV2
        label="登记金额:"
        prop="amount"
        :check-rules="[{ message: '请输入登记金额', type: 'number' }]"
      >
        <ProFormInputNumber
          v-model="form.amount"
          :controls="false"
          :min="0"
          unit="元"
          :precision="2"
        ></ProFormInputNumber>
      </ProFormItemV2>
      <ProFormItemV2
        label="上传登记凭证:"
        prop="certificateUrl"
        :check-rules="[{ message: '请上传登记凭证', type: 'upload' }]"
      >
        <ProFormUpload
          v-model:file-url="form.certificateUrl"
          :limitFileSize="50"
          accept="doc,docx,pdf,xls,xlsx,jpg/jpeg,png"
        ></ProFormUpload>
      </ProFormItemV2>
    </ProForm>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="emit('onCancel')">取 消</el-button>
        <el-button type="primary" @click="handleConfirm">确 定</el-button>
      </span>
    </template>
  </ProDialog>
</template>
<script setup lang="ts">
import { FormInstance, TransferPropsAlias } from 'element-plus';
import {
  ProDialog,
  ProForm,
  ProFormItemV2,
  ProFormInputNumber,
  ProFormRadio,
  ProFormUpload,
  UploadUserFile,
} from '@bole-core/components';
import { Message } from '@bole-core/core';
import { IncomeTypeEnumText, IncomeTypeEnum } from '@/constants';
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
defineOptions({
  name: 'BatchRegisterDialog',
});
type Props = {
  /**
   * @deprecated
   */
  financeSumAmount?: number;
};
const props = withDefaults(defineProps<Props>(), {});
const visible = defineModel({ type: Boolean });
type Form = {
  title?: string;
  parkBountyApplyDetailIds: string[];
  amount: number;
  companyList: API.GetNotTransferCompanyNameListOutput[];
  incomeType: IncomeTypeEnum;
  parkBountyApplyId: string;
  showSuportPlatRecharge: boolean;
  certificateUrl: UploadUserFile[];
};
const form = defineModel<Form>('form');
const incomeTypeEnum = computed(() => {
  return [
    {
      label: IncomeTypeEnumText[IncomeTypeEnum.Fiscal],
      value: IncomeTypeEnum.Fiscal,
    },
    form.value.showSuportPlatRecharge && {
      label: IncomeTypeEnumText[IncomeTypeEnum.Platform],
      value: IncomeTypeEnum.Platform,
    },
  ].filter(Boolean);
});
const deleteList = ref<string[]>([]);
watch(visible, (value, oldValue) => {
  if (value && !oldValue) {
    getParkBountyApplyBatchFinanceEnterprise();
  }
});
async function getParkBountyApplyBatchTransferEnterprise() {
  try {
    let res = await parkBountyApplyServices.getParkBountyApplyBatchTransferEnterprise({
      parkBountyApplyId: form.value.parkBountyApplyId,
    });
    if (res) {
      form.value.companyList = res;
      form.value.parkBountyApplyDetailIds = res.map((x) => x.parkBountyApplyDetailId);
      deleteList.value = [];
    }
  } catch (error) {}
}
async function getParkBountyApplyBatchFinanceEnterprise() {
  try {
    let res = await parkBountyApplyServices.getParkBountyApplyBatchFinanceEnterprise({
      parkBountyApplyId: form.value.parkBountyApplyId,
    });
    if (res) {
      form.value.companyList = res;
      form.value.parkBountyApplyDetailIds = res.map((x) => x.parkBountyApplyDetailId);
      deleteList.value = [];
    }
  } catch (error) {}
}
function handleIncomeTypeChange() {
  if (form.value.incomeType === IncomeTypeEnum.Fiscal) {
    getParkBountyApplyBatchFinanceEnterprise();
  } else {
    getParkBountyApplyBatchTransferEnterprise();
  }
}
function handleChange(ids: string[]) {
  form.value.parkBountyApplyDetailIds = form.value.companyList
    .filter((item) => !ids.includes(item.companyId))
    .map((item) => item.parkBountyApplyDetailId);
}
const emit = defineEmits<{
  (e: 'onConfirm'): void;
  (e: 'onCancel'): void;
}>();
const dialogForm = ref<FormInstance>();
function onDialogClose() {
  if (!dialogForm.value) return;
  dialogForm.value.resetFields();
}
function handleConfirm() {
  if (!form.value.parkBountyApplyDetailIds.length) {
    Message.warnMessage('请选择入账企业');
    return;
  }
  if (!dialogForm.value) return;
  dialogForm.value.validate((valid) => {
    if (valid) {
      emit('onConfirm');
    } else {
      return;
    }
  });
}
const prop = {
  label: 'name',
  key: 'companyId',
} as TransferPropsAlias;
const filterMethod = (query: string, item: API.GetCompanyNameListOutput) => {
  return item.name.toLowerCase().includes(query.toLowerCase());
};
</script>
<style lang="scss" scoped>
.batchEntryRewardBody {
  display: flex;
  justify-content: center;
  width: 100%;
}
</style>
src/views/Reward/components/RegisterGrantDialog.vue
New file
@@ -0,0 +1,121 @@
<template>
  <ProDialog
    title="登记"
    v-model="visible"
    @close="onDialogClose"
    destroy-on-close
    draggable
    width="700px"
  >
    <ProForm :model="form" ref="dialogForm" label-width="120px">
      <ProFormItemV2
        label="登记类型:"
        prop="incomeType"
        :check-rules="[{ message: '请选择登记类型' }]"
      >
        <ProFormRadio
          v-model="form.incomeType"
          :value-enum="incomeTypeEnum"
          :button-style="false"
        />
      </ProFormItemV2>
      <ProFormItemV2
        label="输入金额:"
        prop="financeSumAmount"
        :check-rules="[{ message: '请输入金额', type: 'number' }]"
      >
        <ProFormInputNumber
          v-model="form.financeSumAmount"
          :controls="false"
          :min="0"
          unit="元"
          :precision="2"
        ></ProFormInputNumber>
      </ProFormItemV2>
      <ProFormItemV2
        label="上传凭证:"
        prop="fileUrl"
        :check-rules="[{ message: '请上传凭证', type: 'upload' }]"
      >
        <ProFormUpload
          v-model:file-url="form.fileUrl"
          :limitFileSize="50"
          accept="doc,docx,pdf,xls,xlsx,jpg/jpeg,png"
        ></ProFormUpload>
      </ProFormItemV2>
    </ProForm>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="emit('onCancel')">取 消</el-button>
        <el-button type="primary" @click="handleConfirm">确 定</el-button>
      </span>
    </template>
  </ProDialog>
</template>
<script setup lang="ts">
import { FormInstance } from 'element-plus';
import {
  ProDialog,
  ProForm,
  ProFormItemV2,
  ProFormInputNumber,
  ProFormRadio,
  ProFormUpload,
  UploadUserFile,
} from '@bole-core/components';
import { IncomeTypeEnumText, IncomeTypeEnum, FinanceStatusEnum } from '@/constants';
defineOptions({
  name: 'RegisterGrantDialog',
});
const visible = defineModel({ type: Boolean });
type Form = {
  title?: string;
  financeSumAmount: number;
  fileUrl: UploadUserFile[];
  incomeType: IncomeTypeEnum;
  showSuportPlatRecharge: boolean;
  showSuportFiscalRecharge: boolean;
};
const form = defineModel<Form>('form');
const emit = defineEmits<{
  (e: 'onConfirm'): void;
  (e: 'onCancel'): void;
}>();
const incomeTypeEnum = computed(() => {
  return [
    form.value.showSuportFiscalRecharge && {
      label: IncomeTypeEnumText[IncomeTypeEnum.Fiscal],
      value: IncomeTypeEnum.Fiscal,
    },
    form.value.showSuportPlatRecharge && {
      label: IncomeTypeEnumText[IncomeTypeEnum.Platform],
      value: IncomeTypeEnum.Platform,
    },
  ].filter(Boolean);
});
const dialogForm = ref<FormInstance>();
function onDialogClose() {
  if (!dialogForm.value) return;
  dialogForm.value.resetFields();
}
function handleConfirm() {
  if (!dialogForm.value) return;
  dialogForm.value.validate((valid) => {
    if (valid) {
      emit('onConfirm');
    } else {
      return;
    }
  });
}
</script>
src/views/Reward/components/RewardApplyTradeCheckDialog.vue
@@ -1,6 +1,13 @@
<template>
  <ProDialog title="出账审批" v-model="visible" @close="onDialogClose" destroy-on-close draggable>
    <PortraitTableWithAttachment v-bind="portraitTableWithAttachmentProps" />
    <PortraitTableWithAttachment v-bind="portraitTableWithAttachmentProps">
      <template #title>
        <el-row class="portrait-table-with-attachment-title">
          <el-text style="color: #333333">打款信息</el-text>
          <el-button type="primary" link @click="handleApply">复制</el-button>
        </el-row>
      </template>
    </PortraitTableWithAttachment>
    <ProForm
      :model="form"
      ref="dialogForm"
@@ -103,7 +110,7 @@
  UploadUserFile,
} from '@bole-core/components';
import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
import { usePortraitTableWithAttachment } from '@/hooks';
import { copyTextToClipboard, usePortraitTableWithAttachment } from '@/hooks';
import { convertApi2FormUrl, convertApi2FormUrlOnlyOne } from '@/utils';
import { useQuery } from '@tanstack/vue-query';
import {
@@ -157,11 +164,6 @@
  annexList: computed(() => form.value?.payFileUrl),
  columns: [
    {
      label: '开户账号',
      key: 'userName',
      formatter: () => '1511 2001 2920 0156 069',
    },
    {
      label: '进账单位',
      key: 'enterpriseName',
      formatter: () => '太平财产保险有限公司抚州中心支公司',
@@ -175,6 +177,11 @@
      label: '开户银行',
      key: 'contactPhone',
      formatter: () => '中国工商银行股份有限公司抚州赣东支行',
    },
    {
      label: '开户账号',
      key: 'userName',
      formatter: () => '1511 2001 2920 0156 069',
    },
    // {
    //   label: '企业类型',
@@ -190,19 +197,19 @@
    //   label: '园区类型',
    //   key: 'parkTypeName',
    // },
    // {
    //   label: '消费类型',
    //   key: 'payRemark',
    // },
    {
      label: '申请出账金额',
      key: 'tradeAmount',
      type: 'money',
      label: '消费类型',
      key: 'payRemark',
    },
    {
      label: '申请出账时间',
      label: '出账审核日期',
      key: 'tradeTime',
      type: 'date',
    },
    {
      label: '出账金额',
      key: 'tradeAmount',
      type: 'money',
    },
    {
      label: '资金余额',
@@ -233,4 +240,17 @@
    }
  });
}
function handleApply() {
  copyTextToClipboard(
    `开户名称:${form.value?.societyCreditCode}\n开户银行:${form.value?.contactPhone}\n开户账号:${form.value?.userName}`
  );
}
</script>
<style lang="scss" scoped>
@use '@/style/common.scss' as *;
.portrait-table-with-attachment-title {
  justify-content: space-between;
}
</style>
src/views/Reward/components/UploadFileDialog.vue
New file
@@ -0,0 +1,86 @@
<template>
  <ProDialog
    title="导入"
    v-model="visible"
    @close="onDialogClose"
    destroy-on-close
    draggable
    width="700px"
  >
    <ProForm :model="form" ref="dialogForm" label-width="120px">
      <ProFormItemV2
        label="上传文件:"
        prop="url"
        :check-rules="[{ message: '请上传文件', type: 'upload' }]"
      >
        <ProFormUpload v-model:file-url="form.url" accept="xlsx,xls"></ProFormUpload>
      </ProFormItemV2>
      <ProFormItemV2
        label="上传凭证:"
        prop="certificateUrl"
        :check-rules="[{ message: '请上传凭证', type: 'upload' }]"
      >
        <ProFormUpload
          v-model:file-url="form.certificateUrl"
          :limitFileSize="50"
          accept="doc,docx,pdf,xls,xlsx,jpg/jpeg,png"
        ></ProFormUpload>
      </ProFormItemV2>
    </ProForm>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="emit('onCancel')">取 消</el-button>
        <el-button type="primary" @click="handleConfirm">确 定</el-button>
      </span>
    </template>
  </ProDialog>
</template>
<script setup lang="ts">
import { FormInstance } from 'element-plus';
import {
  ProDialog,
  ProForm,
  ProFormItemV2,
  UploadUserFile,
  ProFormUpload,
} from '@bole-core/components';
defineOptions({
  name: 'UploadCertRewardDialog',
});
const visible = defineModel({ type: Boolean });
type Form = {
  title?: string;
  certificateUrl: UploadUserFile[];
  url: UploadUserFile[];
  parkBountyApplyId: string;
};
const form = defineModel<Form>('form');
const emit = defineEmits<{
  (e: 'onConfirm'): void;
  (e: 'onCancel'): void;
}>();
const dialogForm = ref<FormInstance>();
function onDialogClose() {
  if (!dialogForm.value) return;
  dialogForm.value.resetFields();
}
function handleConfirm() {
  if (!dialogForm.value) return;
  dialogForm.value.validate((valid) => {
    if (valid) {
      emit('onConfirm');
    } else {
      return;
    }
  });
}
</script>
src/views/Reward/constants/columns.ts
@@ -43,13 +43,13 @@
    name: '园区类型',
  },
  {
    id: '22',
    id: '8',
    enCode: 'auditStatus',
    name: '审核状态',
    width: 160,
  },
  {
    id: '21',
    id: '9',
    enCode: 'payRemark',
    name: '消费类型',
    width: 160,
@@ -66,16 +66,24 @@
    name: '申请出账时间',
    width: 160,
  },
  // {
  //   id: '12',
  //   enCode: 'payFileUrl',
  //   name: '出账凭证',
  //   width: 160,
  // },
  {
    id: '9',
    id: '12',
    enCode: 'remianAmount',
    name: '资金余额',
    width: 160,
  },
  {
    id: '13',
    enCode: 'a',
    name: '审核时间',
    width: 160,
  },
]);
export const ImportParkBountyDataHeaderMap = {
  enterpriseName: '企业名称',
  societyCreditCode: '信用代码',
  financeToAmount: '财政拨付金额',
  transferToAmount: '平台拨付金额',
  remark: '备注',
};