wupengfei
2025-11-11 31343bb1d812bdf43a1b61b67be789507b790f5a
feat: 1.3.0.2
6个文件已修改
1个文件已添加
1090 ■■■■ 已修改文件
src/router/index.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/EmploymentManage/EmploymentSignList.vue 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/EmploymentManage/TaskManageList.vue 110 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/FlexJobManage/FlexJobContractManage.vue 618 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/FlexJobManage/FlexJobManage.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/FlexJobManage/components/StaffInfoDialog.vue 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/FlexJobManage/constants/columns.ts 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts
@@ -171,6 +171,19 @@
          icon: 'home',
        },
      },
      {
        path: '/FlexJobContractManage',
        name: 'FlexJobContractManage',
        hidden: false,
        alwaysShow: true,
        component: () => import('@/views/FlexJobManage/FlexJobContractManage.vue'),
        meta: {
          rank: 10012,
          title: '签约管理',
          // rootMenu: true,
          icon: 'home',
        },
      },
    ],
  },
  {
src/views/EmploymentManage/EmploymentSignList.vue
@@ -71,32 +71,32 @@
      onClick: (role) => openDialog(role),
    },
  },
  // {
  //   data: {
  //     enCode: 'recruitBtn',
  //     name: '录用',
  //   },
  //   emits: {
  //     onClick: (role) => setTaskUserHire(role, EnumTaskUserHireStatus.Pass),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetTaskUsersQueryResultItem) =>
  //       row.hireStatus === EnumTaskUserHireStatus.Pass,
  //   },
  // },
  // {
  //   data: {
  //     enCode: 'refuseBtn',
  //     name: '谢绝',
  //   },
  //   emits: {
  //     onClick: (role) => setTaskUserHire(role, EnumTaskUserHireStatus.Refuse),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetTaskUsersQueryResultItem) =>
  //       row.hireStatus !== EnumTaskUserHireStatus.Wait,
  //   },
  // },
  {
    data: {
      enCode: 'recruitBtn',
      name: '录用',
    },
    emits: {
      onClick: (role) => setTaskUserHire(role, EnumTaskUserHireStatus.Pass),
    },
    extraProps: {
      hide: (row: API.GetTaskUsersQueryResultItem) =>
        row.hireStatus === EnumTaskUserHireStatus.Pass,
    },
  },
  {
    data: {
      enCode: 'refuseBtn',
      name: '谢绝',
    },
    emits: {
      onClick: (role) => setTaskUserHire(role, EnumTaskUserHireStatus.Refuse),
    },
    extraProps: {
      hide: (row: API.GetTaskUsersQueryResultItem) =>
        row.hireStatus !== EnumTaskUserHireStatus.Wait,
    },
  },
]);
const router = useRouter();
src/views/EmploymentManage/TaskManageList.vue
@@ -36,14 +36,14 @@
            <SearchInput
              v-model="extraParamState.keywords"
              style="width: 260px"
              placeholder="任务名称"
              placeholder="任务名称/客户"
              @on-click-search="getList"
            >
            </SearchInput>
          </QueryFilterItem>
        </template>
        <template #btn>
          <!-- <el-button @click="goAddOrEdit()" type="primary">发布</el-button> -->
          <el-button @click="goAddOrEdit()" type="primary">发布</el-button>
        </template>
      </ProTableQueryFilterBar>
      <ProTableV2
@@ -88,18 +88,18 @@
});
const operationBtns = defineOperationBtns([
  // {
  //   data: {
  //     enCode: 'editBtn',
  //     name: '编辑',
  //   },
  //   emits: {
  //     onClick: (role) => goAddOrEdit(role),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetTaskInfosQueryResultItem) => row.status === EnumTaskStatus.Complete,
  //   },
  // },
  {
    data: {
      enCode: 'editBtn',
      name: '编辑',
    },
    emits: {
      onClick: (role) => goAddOrEdit(role),
    },
    extraProps: {
      hide: (row: API.GetTaskInfosQueryResultItem) => row.status === EnumTaskStatus.Complete,
    },
  },
  {
    data: {
      enCode: 'detailBtn',
@@ -109,47 +109,47 @@
      onClick: (row: API.GetTaskInfosQueryResultItem) => goDetail(row),
    },
  },
  // {
  //   data: {
  //     enCode: 'publishBtn',
  //     name: '发布',
  //   },
  //   emits: {
  //     onClick: (row: API.GetTaskInfosQueryResultItem) =>
  //       setTaskInfoReleaseStatus(row, EnumTaskReleaseStatus.InProcess),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetTaskInfosQueryResultItem) =>
  //       row.releaseStatus === EnumTaskReleaseStatus.InProcess,
  //   },
  // },
  // {
  //   data: {
  //     enCode: 'unPublishBtn',
  //     name: '停止发布',
  //   },
  //   emits: {
  //     onClick: (row: API.GetTaskInfosQueryResultItem) =>
  //       setTaskInfoReleaseStatus(row, EnumTaskReleaseStatus.Stopped),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetTaskInfosQueryResultItem) =>
  //       row.releaseStatus === EnumTaskReleaseStatus.Stopped,
  //   },
  // },
  // {
  //   data: {
  //     enCode: 'arrangeBtn',
  //     name: '安排',
  //   },
  //   emits: {
  //     onClick: (row: API.GetTaskInfosQueryResultItem) => handleArrange(row),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetTaskInfosQueryResultItem) =>
  //       row.releaseStatus === EnumTaskReleaseStatus.Stopped,
  //   },
  // },
  {
    data: {
      enCode: 'publishBtn',
      name: '发布',
    },
    emits: {
      onClick: (row: API.GetTaskInfosQueryResultItem) =>
        setTaskInfoReleaseStatus(row, EnumTaskReleaseStatus.InProcess),
    },
    extraProps: {
      hide: (row: API.GetTaskInfosQueryResultItem) =>
        row.releaseStatus === EnumTaskReleaseStatus.InProcess,
    },
  },
  {
    data: {
      enCode: 'unPublishBtn',
      name: '停止发布',
    },
    emits: {
      onClick: (row: API.GetTaskInfosQueryResultItem) =>
        setTaskInfoReleaseStatus(row, EnumTaskReleaseStatus.Stopped),
    },
    extraProps: {
      hide: (row: API.GetTaskInfosQueryResultItem) =>
        row.releaseStatus === EnumTaskReleaseStatus.Stopped,
    },
  },
  {
    data: {
      enCode: 'arrangeBtn',
      name: '安排',
    },
    emits: {
      onClick: (row: API.GetTaskInfosQueryResultItem) => handleArrange(row),
    },
    extraProps: {
      hide: (row: API.GetTaskInfosQueryResultItem) =>
        row.releaseStatus === EnumTaskReleaseStatus.Stopped,
    },
  },
]);
const router = useRouter();
src/views/FlexJobManage/FlexJobContractManage.vue
New file
@@ -0,0 +1,618 @@
<template>
  <LoadingLayout :loading="state.loading">
    <AppContainer>
      <ProTableQueryFilterBar @on-reset="reset">
        <template #query>
          <QueryFilterItem tip-content="灵工签约状态">
            <FieldSelect
              v-model="extraParamState.userSignContractStatus"
              :value-enum="EnumTaskUserSignContractStatusText"
              placeholder="请选择灵工签约状态"
              clearable
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem tip-content="企业签约状态">
            <FieldSelect
              v-model="extraParamState.enterpriseSignContractStatus"
              :value-enum="EnumTaskUserSignContractStatusText"
              placeholder="请选择企业签约状态"
              clearable
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem>
            <FieldDatePicker
              v-model="extraParamState.signContractTime"
              type="daterange"
              range-separator="~"
              start-placeholder="起始日期"
              end-placeholder="截止日期"
              clearable
              @change="getList()"
              tooltipContent="灵工签约时间"
            ></FieldDatePicker>
          </QueryFilterItem>
          <QueryFilterItem>
            <FieldDatePicker
              v-model="extraParamState.signContractTime"
              type="daterange"
              range-separator="~"
              start-placeholder="起始日期"
              end-placeholder="截止日期"
              clearable
              @change="getList()"
              tooltipContent="企业签约时间"
            ></FieldDatePicker>
          </QueryFilterItem>
          <QueryFilterItem>
            <SearchInput
              v-model="extraParamState.searchWord"
              style="width: 300px"
              placeholder="姓名/手机/身份证号"
              @on-click-search="getList"
              @keyup.enter="getList()"
            >
            </SearchInput>
          </QueryFilterItem>
        </template>
        <template #btn>
          <!-- <el-button @click="handleDownloadTemplate()" type="primary" link>模板下载</el-button> -->
          <!-- <el-button @click="handleBatchImportAdd()" type="primary">批量导入</el-button> -->
          <!-- <el-button @click="handleStaffInfoAdd()" type="primary">新建</el-button> -->
          <el-button @click="handleBatchUnSign()" type="primary">批量解约</el-button>
          <el-button @click="handleSendShotMessage()" type="primary">短信发送</el-button>
          <el-button @click="handleBatchSign()" type="primary">批量签约</el-button>
          <!-- <el-button @click="handleEnterpriseBatchSign()" type="primary">批量企业签约</el-button> -->
        </template>
      </ProTableQueryFilterBar>
      <ProTableV2
        v-bind="proTableProps"
        :columns="FlexJobContractManageColumns"
        :operationBtns="operationBtns"
        show-column-check
        ref="proTable"
        :table-props="{
          rowKey: 'id',
        }"
      >
      </ProTableV2>
    </AppContainer>
    <StaffInfoDialog v-bind="dialogStaffInfoProps" />
    <StaffDetailInfoDialog v-bind="dialogStaffDetailProps" />
    <BatchImportDialog
      v-bind="dialogBatchImportProps"
      @onDownloadTemplate="handleDownloadTemplate"
    />
    <SendShotMessageDialog v-bind="dialogShotMessageProps" />
    <SignDialog v-bind="dialogSignProps" />
  </LoadingLayout>
</template>
<script setup lang="ts">
import {
  ProTableQueryFilterBar,
  OperationBtnType,
  ProTableV2,
  SearchInput,
  LoadingLayout,
  AppContainer,
  QueryFilterItem,
  useTable,
  FieldDatePicker,
  FieldRadio,
  FieldSelect,
  defineOperationBtns,
  useFormDialog,
  UploadUserFile,
  XLSXUtils,
} from '@bole-core/components';
import { FlexJobContractManageColumns } from './constants';
import { EnumTaskUserHireStatusText, EnumTaskUserSignContractStatusText } from '@/constants';
import { Message } from '@bole-core/core';
import { convertApi2FormUrlOnlyOne, downloadFileByUrl, format } from '@/utils';
import StaffInfoDialog from './components/StaffInfoDialog.vue';
import BatchImportDialog from './components/BatchImportDialog.vue';
import SendShotMessageDialog from './components/SendShotMessageDialog.vue';
import StaffDetailInfoDialog from './components/StaffDetailInfoDialog.vue';
import SignDialog from './components/SignDialog.vue';
import * as enterpriseEmployeeServices from '@/services/api/enterpriseEmployee';
import { ModelValueType } from 'element-plus';
import _ from 'lodash';
defineOptions({
  name: 'FlexJobContractManage',
});
const operationBtns = defineOperationBtns([
  // {
  //   data: {
  //     enCode: 'editBtn',
  //     name: '编辑',
  //   },
  //   emits: {
  //     onClick: (role) => openDialog(role),
  //   },
  // },
  {
    data: {
      enCode: 'detailBtn',
      name: '详情',
    },
    emits: {
      onClick: (role: API.GetEnterpriseEmployeesQueryResultItem) =>
        handleStaffDetailEdit({ id: role.id, tabType: 'info' }),
    },
  },
  {
    data: {
      enCode: 'enterpriseSignBtn',
      name: '企业签约',
    },
    emits: {
      onClick: (role) => handleEnterpriseSign(role),
    },
    extraProps: {
      hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
        !(
          row.userSignContractStatus === EnumTaskUserSignContractStatus.Pass &&
          row.enterpriseSignContractStatus === EnumTaskUserSignContractStatus.Wait
        ),
    },
  },
  {
    data: {
      enCode: 'inviteSignBtn',
      name: '邀请签约',
    },
    emits: {
      onClick: (role) => handleInviteSign(role),
    },
    extraProps: {
      hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
        !(
          row.userSignContractStatus !== EnumTaskUserSignContractStatus.Pass &&
          row.hireStatus === EnumTaskUserHireStatus.Pass
        ),
    },
  },
  {
    data: {
      enCode: 'unSignBtn',
      name: '解约',
    },
    emits: {
      onClick: (role) => handleUnSign(role),
    },
    extraProps: {
      hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
        !(
          row.userSignContractStatus === EnumTaskUserSignContractStatus.Pass &&
          row.enterpriseSignContractStatus === EnumTaskUserSignContractStatus.Pass
        ),
    },
  },
  // {
  //   data: {
  //     enCode: 'delBtn',
  //     name: '删除',
  //   },
  //   props: { type: 'danger' },
  //   emits: {
  //     onClick: (role) => handleDelete(role),
  //   },
  // },
]);
const router = useRouter();
const BaseState = {
  loading: true,
};
const state = reactive({ ...BaseState });
onMounted(async () => {
  await getList();
  state.loading = false;
});
const {
  getDataSource: getList,
  proTableProps,
  paginationState,
  extraParamState,
  reset,
} = useTable(
  async ({ pageIndex, pageSize }, extraParamState) => {
    try {
      let params: API.GetEnterpriseEmployeesQuery = {
        pageModel: {
          rows: pageSize,
          page: pageIndex,
          orderInput: extraParamState.orderInput,
        },
        keywords: extraParamState.searchWord,
        createdTimeStart: format(extraParamState.createdTime?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
        createdTimeEnd: format(extraParamState.createdTime?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
        signContractTimeStart: format(
          extraParamState.signContractTime?.[0] ?? '',
          'YYYY-MM-DD 00:00:00'
        ),
        signContractTimeEnd: format(
          extraParamState.signContractTime?.[1] ?? '',
          'YYYY-MM-DD 23:59:59'
        ),
        hireStatus: extraParamState.hireStatus,
        isReal: extraParamState.isReal,
        userSignContractStatus: extraParamState.userSignContractStatus,
        enterpriseSignContractStatus: extraParamState.enterpriseSignContractStatus,
      };
      let res = await enterpriseEmployeeServices.getEnterpriseEmployees(params, {
        showLoading: !state.loading,
      });
      return res;
    } catch (error) {
      console.log('error: ', error);
    }
  },
  {
    defaultExtraParams: {
      searchWord: '',
      orderInput: [{ property: 'createdTime', order: EnumPagedListOrder.Desc }],
      createdTime: [] as unknown as ModelValueType,
      signContractTime: [] as unknown as ModelValueType,
      hireStatus: '' as any as EnumTaskUserHireStatus,
      isReal: null as any as boolean,
      userSignContractStatus: '' as any as EnumTaskUserSignContractStatus,
      enterpriseSignContractStatus: '' as any as EnumTaskUserSignContractStatus,
    },
    queryKey: ['enterpriseEmployeeServices/getEnterpriseEmployees'],
    columnsRenderProps: {
      gender: { type: 'enum', valueEnum: EnumUserGenderTextForPerson },
      hireStatus: { type: 'enum', valueEnum: EnumTaskUserHireStatusText },
      userIsReal: {
        formatter: (row: API.GetEnterpriseEmployeesQueryResultItem) => {
          return row.userIsReal ? '已实名' : '未实名';
        },
      },
      userSignContractStatus: { type: 'enum', valueEnum: EnumTaskUserSignContractStatusText },
      hireTime: { type: 'date' },
      userRealTime: { type: 'date' },
      userSignContractTime: { type: 'date' },
      enterpriseSignContractStatus: { type: 'enum', valueEnum: EnumTaskUserSignContractStatusText },
      enterpriseSignContractTime: { type: 'date' },
    },
  }
);
const proTable = ref<InstanceType<typeof ProTableV2>>();
function getSelectionRows() {
  if (proTableProps.value.tableData.length) {
    const res = proTable.value.innerTableRef.getSelectionRows();
    if (res.length > 0) {
      return res;
    } else {
      Message.errorMessage('未选择数据');
    }
  } else {
    Message.errorMessage('暂无数据');
  }
}
const {
  dialogProps: dialogStaffInfoProps,
  handleEdit: handleStaffInfoEdit,
  handleAdd: handleStaffInfoAdd,
  editForm: staffInfoEditForm,
} = useFormDialog({
  onConfirm: handleAddOrEdit,
  defaultFormParams: {
    id: '',
    name: '',
    identity: '',
    contactPhoneNumber: '',
    gender: EnumUserGender.Male,
    age: null as any as number,
    identityImg: [] as UploadUserFile[],
    identityBackImg: [] as UploadUserFile[],
    contractUrl: [] as UploadUserFile[],
    regiterTime: '',
    userRealTime: '',
    userSignContractTime: '',
    isDetail: false,
  },
});
async function openDialog(row: API.GetEnterpriseEmployeesQueryResultItem, isDetail = false) {
  try {
    let detail = await enterpriseEmployeeServices.getEnterpriseEmployee({ id: row.id });
    handleStaffInfoEdit({
      id: row.id,
      name: row.name,
      identity: row.identity,
      contactPhoneNumber: row.contactPhoneNumber,
      gender: detail.gender,
      age: detail.age ?? null,
      identityImg: convertApi2FormUrlOnlyOne(detail.identityImg),
      identityBackImg: convertApi2FormUrlOnlyOne(detail.identityBackImg),
      contractUrl: convertApi2FormUrlOnlyOne(detail.contractUrl, {
        fileName: detail.contractUrl ? detail.contractUrl.split('/').pop() : '合同',
      }),
      regiterTime: detail.applyTime ?? '',
      userRealTime: row.userRealTime ?? '',
      userSignContractTime: row.userSignContractTime ?? '',
      isDetail: isDetail,
    });
  } catch (error) {}
}
async function handleAddOrEdit() {
  try {
    let params: API.EditEnterpriseEmployeeCommand = {
      name: staffInfoEditForm.name,
      identity: staffInfoEditForm.identity,
      contactPhoneNumber: staffInfoEditForm.contactPhoneNumber,
      gender: staffInfoEditForm.gender,
      age: staffInfoEditForm.age,
      identityImg: staffInfoEditForm.identityImg[0]?.path ?? '',
      identityBackImg: staffInfoEditForm.identityBackImg[0]?.path ?? '',
      id: staffInfoEditForm.id,
    };
    let res = await enterpriseEmployeeServices.editEnterpriseEmployee(params);
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
    }
  } catch (error) {}
}
const {
  dialogProps: dialogBatchImportProps,
  handleAdd: handleBatchImportAdd,
  editForm: batchImportForm,
} = useFormDialog({
  onConfirm: handleBatchImport,
  defaultFormParams: {
    url: [] as UploadUserFile[],
  },
});
async function handleBatchImport() {
  try {
    let params: API.ImportEnterpriseEmployeesCommand = {
      excelUrl: batchImportForm.url[0]?.path ?? '',
    };
    let res = await enterpriseEmployeeServices.importEnterpriseEmployees(params);
    if (res.failCount > 0) {
      await Message.tipMessage('存在错误数据,是否导出?');
      XLSXUtils.exportToXLSX({
        workbookDataList: res.errors,
        fileName: '灵工批量导入-错误数据',
        workbookHeaderMap: {
          name: '姓名',
          identity: '身份证号',
          contactPhoneNumber: '手机号',
          errorMessage: '备注',
        },
      });
    } else {
      Message.successMessage('导入成功');
      getList();
    }
  } catch (error) {}
}
const {
  dialogProps: dialogShotMessageProps,
  handleAdd: handleShotMessageAdd,
  editForm: editShotMessageForm,
} = useFormDialog({
  onConfirm: sendMessageForSign,
  defaultFormParams: {
    ids: [] as string[],
    customerId: '',
    name: '',
    contractTemplateId: '',
  },
});
async function handleSendShotMessage() {
  try {
    const selectionRows = getSelectionRows();
    if (selectionRows) {
      if (
        selectionRows.some((x) => x.userSignContractStatus === EnumTaskUserSignContractStatus.Pass)
      ) {
        await Message.tipMessage('勾选人员中包含已签约完成人员,确认要继续发送短信通知吗?');
      }
      handleShotMessageAdd({
        ids: selectionRows.map((x) => x.id),
        name: '人员签约通道短信',
      });
    }
  } catch (error) {}
}
async function sendMessageForSign() {
  try {
    let params: API.SendInviteElectronSignSmsCommand = {
      ids: editShotMessageForm.ids,
      contractTemplateId: editShotMessageForm.contractTemplateId,
    };
    let res = await enterpriseEmployeeServices.sendInviteElectronSignSms(params);
    if (res) {
      Message.successMessage('短信已发送');
    }
  } catch (error) {}
}
function handleDownloadTemplate() {
  downloadFileByUrl(ImportEnterpriseEmployeesTempPath, '批量导入模板');
}
const {
  dialogProps: dialogSignProps,
  handleAdd: handleSignAdd,
  handleEdit: handleSignEdit,
  editForm: signEditForm,
} = useFormDialog({
  onConfirm: signContract,
  defaultFormParams: {
    ids: [] as string[],
    contractTemplateId: '',
  },
});
function handleInviteSign(row: API.GetEnterpriseEmployeesQueryResultItem) {
  if (row) {
    handleSignEdit({
      ids: [row.id],
      contractTemplateId: '',
    });
  }
}
function handleBatchSign() {
  const selectionRows = getSelectionRows();
  if (selectionRows) {
    const hasSigned = selectionRows?.some(
      (x) =>
        x.userSignContractStatus === EnumTaskUserSignContractStatus.Pass ||
        x.enterpriseSignContractStatus === EnumTaskUserSignContractStatus.Pass ||
        x.hireStatus === EnumTaskUserHireStatus.Wait
    );
    if (hasSigned) {
      Message.warnMessage('勾选人员中包含已签约完成或未录用人员');
      return;
    }
    handleSignAdd({
      ids: selectionRows.map((x) => x.id),
      contractTemplateId: '',
    });
  }
}
const handleEnterpriseBatchSign = _.debounce(
  () => {
    const selectionRows = getSelectionRows();
    if (selectionRows) {
      const hasSigned = selectionRows?.some(
        (x) =>
          !(
            x.userSignContractStatus === EnumTaskUserSignContractStatus.Pass &&
            x.enterpriseSignContractStatus === EnumTaskUserSignContractStatus.Wait
          )
      );
      if (hasSigned) {
        Message.warnMessage('勾选人员中包含已企业签约、未录用人员或未签约完成人员');
        return;
      }
      const ids = selectionRows.map((x) => x.id);
      handleBatchEnterpriseSign(ids);
    }
  },
  1000,
  { leading: true, trailing: false }
);
async function handleBatchEnterpriseSign(ids: string[]) {
  try {
    state.loading = true;
    let res = await enterpriseEmployeeServices.batchEnterpriseSignContract({ ids: ids });
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
      if (res?.errors?.length > 0) {
        Message.tipMessage('存在签约失败的灵工信息数据,是否导出?').then(() => {
          XLSXUtils.exportToXLSX({
            workbookDataList: res.errors,
            fileName: '签约失败灵工信息',
            workbookHeaderMap: {
              name: '姓名',
              contactPhoneNumber: '手机号',
              identity: '身份证号',
              errorMessages: '错误信息',
            },
          });
        });
      }
    }
  } catch (error) {
  } finally {
    state.loading = false;
  }
}
async function signContract() {
  try {
    let params: API.InviteElectronSignCommand = {
      ids: signEditForm.ids,
      contractTemplateId: signEditForm.contractTemplateId,
    };
    let res = await enterpriseEmployeeServices.inviteElectronSign(params);
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
    }
  } catch (error) {}
}
async function handleEnterpriseSign(row: API.GetEnterpriseEmployeesQueryResultItem) {
  try {
    let res = await enterpriseEmployeeServices.enterpriseUserElectronSign({ id: row.id });
    if (res) {
      window.open(res?.signContractLongUrl, '_blank');
    }
  } catch (error) {}
}
function handleUnSign(row: API.GetEnterpriseEmployeesQueryResultItem) {
  stopElectronSign([row.id]);
}
function handleBatchUnSign() {
  try {
    const selectionRows = getSelectionRows();
    if (selectionRows) {
      const hasUnSigned = selectionRows?.some(
        (x) => x.enterpriseSignContractStatus !== EnumTaskUserSignContractStatus.Pass
      );
      if (hasUnSigned) {
        Message.warnMessage('勾选数据中包含企业未签约或已解约数据');
        return;
      }
      stopElectronSign(selectionRows.map((x) => x.id));
    }
  } catch (error) {}
}
async function stopElectronSign(ids: string[]) {
  try {
    await Message.tipMessage('确定解约用户?');
    let res = await enterpriseEmployeeServices.stopElectronSign({ ids: ids });
    if (res) {
      Message.successMessage('操作成功');
      getList(paginationState.pageIndex);
    }
  } catch (error) {}
}
const {
  dialogProps: dialogStaffDetailProps,
  handleEdit: handleStaffDetailEdit,
  editForm: staffDetailEditForm,
} = useFormDialog({
  defaultFormParams: {
    id: '',
    tabType: 'info',
  },
});
async function handleDelete(row: API.GetEnterpriseEmployeesQueryResultItem) {
  try {
    await Message.deleteMessage();
  } catch (error) {}
}
</script>
src/views/FlexJobManage/FlexJobManage.vue
@@ -3,7 +3,7 @@
    <AppContainer>
      <ProTableQueryFilterBar @on-reset="reset">
        <template #query>
          <QueryFilterItem tip-content="录用状态">
          <!-- <QueryFilterItem tip-content="录用状态">
            <FieldRadio
              v-model="extraParamState.hireStatus"
              :value-enum="EnumTaskUserHireStatusText"
@@ -11,7 +11,7 @@
              showAllBtn
              @change="getList()"
            />
          </QueryFilterItem>
          </QueryFilterItem> -->
          <QueryFilterItem tip-content="实名状态">
            <FieldRadio
              v-model="extraParamState.isReal"
@@ -19,6 +19,16 @@
                { label: '已实名', value: true },
                { label: '未实名', value: false },
              ]"
              buttonStyle
              showAllBtn
              :all-btn-value="null"
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem tip-content="灵工来源">
            <FieldRadio
              v-model="extraParamState.isReal"
              :value-enum="[]"
              buttonStyle
              showAllBtn
              :all-btn-value="null"
@@ -43,7 +53,7 @@
              @change="getList()"
            />
          </QueryFilterItem>
          <QueryFilterItem>
          <!-- <QueryFilterItem>
            <FieldDatePicker
              v-model="extraParamState.createdTime"
              type="daterange"
@@ -66,12 +76,24 @@
              @change="getList()"
              tooltipContent="签约时间"
            ></FieldDatePicker>
          </QueryFilterItem> -->
          <QueryFilterItem>
            <FieldDatePicker
              v-model="extraParamState.createdTime"
              type="daterange"
              range-separator="~"
              start-placeholder="起始日期"
              end-placeholder="截止日期"
              clearable
              @change="getList()"
              tooltipContent="实名时间"
            ></FieldDatePicker>
          </QueryFilterItem>
          <QueryFilterItem>
            <SearchInput
              v-model="extraParamState.searchWord"
              style="width: 300px"
              placeholder="姓名/手机/身份证号/客户"
              placeholder="姓名/手机/身份证号"
              @on-click-search="getList"
              @keyup.enter="getList()"
            >
@@ -81,10 +103,11 @@
        <template #btn>
          <el-button @click="handleDownloadTemplate()" type="primary" link>模板下载</el-button>
          <el-button @click="handleBatchImportAdd()" type="primary">批量导入</el-button>
          <el-button @click="handleBatchUnSign()" type="primary">批量解约</el-button>
          <el-button @click="handleStaffInfoAdd()" type="primary">新建</el-button>
          <!-- <el-button @click="handleBatchUnSign()" type="primary">批量解约</el-button>
          <el-button @click="handleSendShotMessage()" type="primary">短信发送</el-button>
          <el-button @click="handleBatchSign()" type="primary">批量签约</el-button>
          <el-button @click="handleEnterpriseBatchSign()" type="primary">批量企业签约</el-button>
          <el-button @click="handleEnterpriseBatchSign()" type="primary">批量企业签约</el-button> -->
        </template>
      </ProTableQueryFilterBar>
      <ProTableV2
@@ -146,15 +169,15 @@
});
const operationBtns = defineOperationBtns([
  {
    data: {
      enCode: 'editBtn',
      name: '编辑',
    },
    emits: {
      onClick: (role) => openDialog(role),
    },
  },
  // {
  //   data: {
  //     enCode: 'editBtn',
  //     name: '编辑',
  //   },
  //   emits: {
  //     onClick: (role) => openDialog(role),
  //   },
  // },
  {
    data: {
      enCode: 'detailBtn',
@@ -165,54 +188,54 @@
        handleStaffDetailEdit({ id: role.id, tabType: 'info' }),
    },
  },
  {
    data: {
      enCode: 'enterpriseSignBtn',
      name: '企业签约',
    },
    emits: {
      onClick: (role) => handleEnterpriseSign(role),
    },
    extraProps: {
      hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
        !(
          row.userSignContractStatus === EnumTaskUserSignContractStatus.Pass &&
          row.enterpriseSignContractStatus === EnumTaskUserSignContractStatus.Wait
        ),
    },
  },
  {
    data: {
      enCode: 'inviteSignBtn',
      name: '邀请签约',
    },
    emits: {
      onClick: (role) => handleInviteSign(role),
    },
    extraProps: {
      hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
        !(
          row.userSignContractStatus !== EnumTaskUserSignContractStatus.Pass &&
          row.hireStatus === EnumTaskUserHireStatus.Pass
        ),
    },
  },
  {
    data: {
      enCode: 'unSignBtn',
      name: '解约',
    },
    emits: {
      onClick: (role) => handleUnSign(role),
    },
    extraProps: {
      hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
        !(
          row.userSignContractStatus === EnumTaskUserSignContractStatus.Pass &&
          row.enterpriseSignContractStatus === EnumTaskUserSignContractStatus.Pass
        ),
    },
  },
  // {
  //   data: {
  //     enCode: 'enterpriseSignBtn',
  //     name: '企业签约',
  //   },
  //   emits: {
  //     onClick: (role) => handleEnterpriseSign(role),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
  //       !(
  //         row.userSignContractStatus === EnumTaskUserSignContractStatus.Pass &&
  //         row.enterpriseSignContractStatus === EnumTaskUserSignContractStatus.Wait
  //       ),
  //   },
  // },
  // {
  //   data: {
  //     enCode: 'inviteSignBtn',
  //     name: '邀请签约',
  //   },
  //   emits: {
  //     onClick: (role) => handleInviteSign(role),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
  //       !(
  //         row.userSignContractStatus !== EnumTaskUserSignContractStatus.Pass &&
  //         row.hireStatus === EnumTaskUserHireStatus.Pass
  //       ),
  //   },
  // },
  // {
  //   data: {
  //     enCode: 'unSignBtn',
  //     name: '解约',
  //   },
  //   emits: {
  //     onClick: (role) => handleUnSign(role),
  //   },
  //   extraProps: {
  //     hide: (row: API.GetEnterpriseEmployeesQueryResultItem) =>
  //       !(
  //         row.userSignContractStatus === EnumTaskUserSignContractStatus.Pass &&
  //         row.enterpriseSignContractStatus === EnumTaskUserSignContractStatus.Pass
  //       ),
  //   },
  // },
  // {
  //   data: {
  //     enCode: 'delBtn',
@@ -326,6 +349,7 @@
const {
  dialogProps: dialogStaffInfoProps,
  handleEdit: handleStaffInfoEdit,
  handleAdd: handleStaffInfoAdd,
  editForm: staffInfoEditForm,
} = useFormDialog({
  onConfirm: handleAddOrEdit,
src/views/FlexJobManage/components/StaffInfoDialog.vue
@@ -15,8 +15,13 @@
          </ProFormItemV2>
        </ProFormColItem>
        <ProFormColItem :span="12">
          <ProFormItemV2 v-if="form.isDetail" label="报名时间:" prop="regiterTime">
            <div>{{ format(form.regiterTime, 'YYYY-MM-DD HH:mm') }}</div>
          <ProFormItemV2 label="服务协议:" prop="contractUrl">
            <ProFormUpload
              v-model:file-url="form.contractUrl"
              :limit="1"
              :limitFileSize="10"
              accept="jpg/jpeg,png,pdf"
            ></ProFormUpload>
          </ProFormItemV2>
        </ProFormColItem>
        <ProFormColItem :span="12">
@@ -33,8 +38,18 @@
          </ProFormItemV2>
        </ProFormColItem>
        <ProFormColItem :span="12">
          <ProFormItemV2 v-if="form.isDetail" label="实名时间:" prop="userRealTime">
            <div>{{ format(form.userRealTime, 'YYYY-MM-DD HH:mm') }}</div>
          <ProFormItemV2
            label="协议时间:"
            prop="regiterTime"
            :check-rules="[{ message: '请选择协议时间', type: 'array' }]"
          >
            <ProFormDatePicker
              v-model="form.regiterTime"
              type="daterange"
              range-separator="至"
              start-placeholder="起始日期"
              end-placeholder="终止日期"
            ></ProFormDatePicker>
          </ProFormItemV2>
        </ProFormColItem>
        <ProFormColItem :span="12">
@@ -49,11 +64,7 @@
            ></ProFormText>
          </ProFormItemV2>
        </ProFormColItem>
        <ProFormColItem :span="12">
          <ProFormItemV2 v-if="form.isDetail" label="签约时间:" prop="userSignContractTime">
            <div>{{ format(form.userSignContractTime, 'YYYY-MM-DD HH:mm') }}</div>
          </ProFormItemV2>
        </ProFormColItem>
        <ProFormColItem :span="12"> </ProFormColItem>
        <ProFormColItem :span="12">
          <ProFormItemV2
            label="性别:"
@@ -68,16 +79,7 @@
            ></ProFormRadio>
          </ProFormItemV2>
        </ProFormColItem>
        <ProFormColItem :span="12">
          <ProFormItemV2 v-if="form.isDetail" label="电子合同:" prop="contractUrl">
            <ProFormUpload
              v-model:file-url="form.contractUrl"
              :limit="1"
              :limitFileSize="10"
              accept="jpg/jpeg,png,pdf"
            ></ProFormUpload>
          </ProFormItemV2>
        </ProFormColItem>
        <ProFormColItem :span="12"> </ProFormColItem>
        <ProFormColItem :span="12">
          <ProFormItemV2
            label="年龄:"
@@ -90,12 +92,8 @@
              :min="0"
              :max="9999"
              placeholder="请输入年龄"
            >
              <template #readContent>
                <span v-if="form.age">{{ form.age }}岁</span>
                <span v-else></span>
              </template>
            </ProFormInputNumber>
              unit="岁"
            />
          </ProFormItemV2>
        </ProFormColItem>
      </ProFormCol>
@@ -129,7 +127,7 @@
        <el-button v-if="form.isDetail" @click="emit('onCancel')">关闭</el-button>
        <template v-else>
          <el-button type="primary" @click="handleConfirm">提交</el-button>
          <el-button @click="handleReset">重置</el-button>
          <!-- <el-button @click="handleReset">重置</el-button> -->
          <el-button @click="emit('onCancel')">取消</el-button>
        </template>
      </span>
@@ -151,6 +149,7 @@
  ProFormRadio,
  ProFormUpload,
  ProFormInputNumber,
  ProFormDatePicker,
} from '@bole-core/components';
import { calculateAge, deepClone, format } from '@/utils';
import { EnumUserGender, EnumUserGenderTextForPerson } from '@/constants';
src/views/FlexJobManage/constants/columns.ts
@@ -26,11 +26,11 @@
    enCode: 'contactPhoneNumber',
    name: '手机号',
  },
  {
    id: '8',
    enCode: 'hireStatus',
    name: '录用状态',
  },
  // {
  //   id: '8',
  //   enCode: 'hireStatus',
  //   name: '录用状态',
  // },
  {
    id: '9',
    enCode: 'userIsReal',
@@ -41,15 +41,93 @@
    enCode: 'userSignContractStatus',
    name: '灵工签约状态',
  },
  // {
  //   id: '11',
  //   enCode: 'hireTime',
  //   name: '录用时间',
  // },
  // {
  //   id: '12',
  //   enCode: 'userRealTime',
  //   name: '实名时间',
  // },
  // {
  //   id: '13',
  //   enCode: 'userSignContractTime',
  //   name: '签约时间',
  // },
  {
    id: '14',
    enCode: 'enterpriseSignContractStatus',
    name: '企业签约状态',
  },
  // {
  //   id: '15',
  //   enCode: 'enterpriseSignContractTime',
  //   name: '企业签约时间',
  // },
  {
    id: '16',
    enCode: 'a',
    name: '协议起始',
  },
  {
    id: '17',
    enCode: 'a',
    name: '协议终止',
  },
  {
    id: '18',
    enCode: 'a',
    name: '灵工来源',
  },
]);
export const FlexJobContractManageColumns = defineColumns([
  {
    id: '1',
    enCode: 'name',
    name: '姓名',
  },
  {
    id: '2',
    enCode: 'identity',
    name: '身份证号',
  },
  {
    id: '3',
    enCode: 'gender',
    name: '性别',
  },
  {
    id: '5',
    enCode: 'age',
    name: '年龄',
  },
  {
    id: '6',
    enCode: 'contactPhoneNumber',
    name: '手机号',
  },
  {
    id: '9',
    enCode: 'userIsReal',
    name: '实名状态',
  },
  {
    id: '10',
    enCode: 'userRealTime',
    name: '实名时间',
  },
  {
    id: '11',
    enCode: 'hireTime',
    name: '录用时间',
    enCode: 'a',
    name: '灵工来源',
  },
  {
    id: '12',
    enCode: 'userRealTime',
    name: '实名时间',
    enCode: 'userSignContractStatus',
    name: '灵工签约状态',
  },
  {
    id: '13',