zhengyiming
20 小时以前 0ca66ba6d5f5d5502211b9d9c7bff036ebd3f1aa
fix: 验收管理
1个文件已添加
13个文件已修改
287 ■■■■ 已修改文件
.eslintrc-auto-import.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
auto-imports.d.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constants/enterpriseEmployee.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/enterpriseEmployee.ts 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/index.ts 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/taskUser.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/services/api/typings.d.ts 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/common/deepClone.ts 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/common/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/EmploymentManage/CheckReceiveTaskDetail.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/FlexJobManage/FlexJobManage.vue 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/FlexJobManage/components/BatchImportDialog.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/FlexJobManage/components/StaffInfoDialog.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintrc-auto-import.json
@@ -75,6 +75,7 @@
    "GlobalEventContext": true,
    "GlobalEventListener": true,
    "IdentityCodeEnum": true,
    "ImportEnterpriseEmployeesTempPath": true,
    "InjectionKey": true,
    "MaybeRef": true,
    "MaybeRefOrGetter": true,
auto-imports.d.ts
@@ -78,6 +78,7 @@
  const GetTaskInfoQueryResultApplyButton: typeof import('./src/constants/apiEnum')['GetTaskInfoQueryResultApplyButton']
  const GetTaskInfoQueryResultHireButton: typeof import('./src/constants/apiEnum')['GetTaskInfoQueryResultHireButton']
  const IdentityCodeEnum: typeof import('./src/constants/dic')['IdentityCodeEnum']
  const ImportEnterpriseEmployeesTempPath: typeof import('./src/constants/enterpriseEmployee')['ImportEnterpriseEmployeesTempPath']
  const MenuSvgIconMap: typeof import('./src/constants/menu')['MenuSvgIconMap']
  const ModuleColumns: typeof import('./src/constants/module')['ModuleColumns']
  const MyRegExp: typeof import('./src/constants/regExp')['MyRegExp']
@@ -302,6 +303,7 @@
    readonly GetTaskInfoQueryResultApplyButton: UnwrapRef<typeof import('./src/constants/apiEnum')['GetTaskInfoQueryResultApplyButton']>
    readonly GetTaskInfoQueryResultHireButton: UnwrapRef<typeof import('./src/constants/apiEnum')['GetTaskInfoQueryResultHireButton']>
    readonly IdentityCodeEnum: UnwrapRef<typeof import('./src/constants/dic')['IdentityCodeEnum']>
    readonly ImportEnterpriseEmployeesTempPath: UnwrapRef<typeof import('./src/constants/enterpriseEmployee')['ImportEnterpriseEmployeesTempPath']>
    readonly MenuSvgIconMap: UnwrapRef<typeof import('./src/constants/menu')['MenuSvgIconMap']>
    readonly ModuleColumns: UnwrapRef<typeof import('./src/constants/module')['ModuleColumns']>
    readonly MyRegExp: UnwrapRef<typeof import('./src/constants/regExp')['MyRegExp']>
src/constants/enterpriseEmployee.ts
@@ -11,3 +11,5 @@
  [EnumTaskUserSignContractStatus.Pass]: '已签约',
  [EnumTaskUserSignContractStatus.Refuse]: '已谢绝',
};
export const ImportEnterpriseEmployeesTempPath = `${TempFolderPath}/%E7%81%B5%E5%B7%A5%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xlsx`;
src/services/api/enterpriseEmployee.ts
@@ -58,12 +58,15 @@
  body: API.ImportEnterpriseEmployeesCommand,
  options?: API.RequestConfig
) {
  return request<number>('/api/user/enterpriseEmployee/importEnterpriseEmployees', {
  return request<API.ImportEnterpriseEmployeesCommandResult>(
    '/api/user/enterpriseEmployee/importEnterpriseEmployees',
    {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
    }
  );
}
src/services/api/index.ts
@@ -3,27 +3,27 @@
// API 更新时间:
// API 唯一标识:
import * as enterpriseEmployee from './enterpriseEmployee';
import * as user from './user';
import * as role from './role';
import * as enterprise from './enterprise';
import * as task from './task';
import * as taskCheckReceive from './taskCheckReceive';
import * as dictionary from './dictionary';
import * as user from './user';
import * as userResume from './userResume';
import * as auth from './auth';
import * as taskCheckReceive from './taskCheckReceive';
import * as resource from './resource';
import * as taskUser from './taskUser';
import * as menu from './menu';
export default {
  enterpriseEmployee,
  user,
  role,
  enterprise,
  task,
  taskCheckReceive,
  dictionary,
  user,
  userResume,
  auth,
  taskCheckReceive,
  resource,
  taskUser,
  menu,
src/services/api/taskUser.ts
@@ -41,6 +41,24 @@
  });
}
/** 查询应聘报名人员录用状态 GET /api/flexjob/taskUser/getTaskUserHireStatus */
export async function getTaskUserHireStatus(
  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
  params: API.APIgetTaskUserHireStatusParams,
  options?: API.RequestConfig
) {
  return request<API.GetTaskUserHireStatusQueryResult>(
    '/api/flexjob/taskUser/getTaskUserHireStatus',
    {
      method: 'GET',
      params: {
        ...params,
      },
      ...(options || {}),
    }
  );
}
/** B端查询应聘报名分页列表信息 POST /api/flexjob/taskUser/getTaskUsers */
export async function getTaskUsers(body: API.GetTaskUsersQuery, options?: API.RequestConfig) {
  return request<API.GetTaskUsersQueryResult>('/api/flexjob/taskUser/getTaskUsers', {
src/services/api/typings.d.ts
@@ -133,6 +133,13 @@
    id?: string;
  }
  interface APIgetTaskUserHireStatusParams {
    /** 任务Id */
    taskInfoId?: string;
    /** 用户Id(C端用户可不填) */
    userId?: string;
  }
  interface APIgetUserInfoRolesParams {
    /** 用户Id */
    userInfoId?: string;
@@ -247,11 +254,11 @@
  interface EditEnterpriseEmployeeCommand {
    /** 姓名 */
    name?: string;
    name: string;
    /** 身份证号 */
    identity?: string;
    identity: string;
    /** 手机号 */
    contactPhoneNumber?: string;
    contactPhoneNumber: string;
    gender?: EnumUserGender;
    /** 年龄 */
    age?: number;
@@ -913,6 +920,24 @@
    timestamp?: number;
  }
  interface FriendlyResultGetTaskUserHireStatusQueryResult {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    data?: GetTaskUserHireStatusQueryResult;
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultGetTaskUsersQueryResult {
    /** 跟踪Id */
    traceId?: string;
@@ -1066,6 +1091,24 @@
    errorCode?: string;
    /** 数据 */
    data?: string;
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
    msg?: any;
    /** 附加数据 */
    extras?: any;
    /** 时间戳 */
    timestamp?: number;
  }
  interface FriendlyResultImportEnterpriseEmployeesCommandResult {
    /** 跟踪Id */
    traceId?: string;
    /** 状态码 */
    code?: number;
    /** 错误码 */
    errorCode?: string;
    data?: ImportEnterpriseEmployeesCommandResult;
    /** 执行成功 */
    success?: boolean;
    /** 错误信息 */
@@ -1586,6 +1629,8 @@
  interface GetCheckReceiveTaskUserSubmitsQuery {
    /** 任务人员Id */
    id?: string;
    /** 任务Id */
    taskInfoId?: string;
    pageModel?: PagedListQueryPageModel;
  }
@@ -2582,6 +2627,10 @@
    stoppedReleaseCount?: number;
  }
  interface GetTaskUserHireStatusQueryResult {
    hireStatus?: EnumTaskUserHireStatus;
  }
  interface GetTaskUsersQuery {
    /** 任务Id */
    id?: string;
@@ -2908,6 +2957,28 @@
    excelUrl?: string;
  }
  interface ImportEnterpriseEmployeesCommandResult {
    /** 总数 */
    totalCount?: number;
    /** 成功数量 */
    successCount?: number;
    /** 失败数量 */
    failCount?: number;
    /** 错误信息 */
    errors?: ImportEnterpriseEmployeesCommandResultError[];
  }
  interface ImportEnterpriseEmployeesCommandResultError {
    /** 错误信息 */
    errorMessage?: string;
    /** 姓名 */
    name?: string;
    /** 手机号 */
    contactPhoneNumber?: string;
    /** 身份证号 */
    identity?: string;
  }
  interface LoginCommandCallback {
    /** 用户Id */
    id?: string;
src/utils/common/deepClone.ts
New file
@@ -0,0 +1,52 @@
/**
 * 深度拷贝函数,支持多种数据类型和循环引用
 * @param target 需要拷贝的目标值
 * @param map 用于处理循环引用的映射表(内部使用)
 * @returns 拷贝后的新值
 */
export function deepClone<T>(target: T, map = new WeakMap<any, any>()): T {
  // 基本类型直接返回(null 特殊处理)
  if (target === null || typeof target !== 'object') {
    return target;
  }
  // 处理循环引用
  if (map.has(target)) {
    return map.get(target);
  }
  let cloneResult: any;
  const Constructor = target.constructor;
  // 处理日期
  if (target instanceof Date) {
    //@ts-ignore
    cloneResult = new Constructor(target) as Date;
    map.set(target, cloneResult);
    return cloneResult as unknown as T;
  }
  // 处理正则
  if (target instanceof RegExp) {
    //@ts-ignore
    cloneResult = new Constructor(target.source, target.flags) as RegExp;
    cloneResult.lastIndex = target.lastIndex; // 复制lastIndex属性
    map.set(target, cloneResult);
    return cloneResult as unknown as T;
  }
  // 处理数组和对象
  //@ts-ignore
  cloneResult = new Constructor() as T;
  map.set(target, cloneResult); // 存储映射关系,防止循环引用
  // 遍历对象属性(包括Symbol键)
  Reflect.ownKeys(target).forEach((key) => {
    // 只拷贝自身属性,不拷贝原型链上的属性
    if (Object.prototype.hasOwnProperty.call(target, key)) {
      cloneResult[key] = deepClone((target as any)[key], map);
    }
  });
  return cloneResult;
}
src/utils/common/index.ts
@@ -14,3 +14,4 @@
export * from './vueHelper';
export * from './categoryUtils';
export * from './encrypt';
export * from './deepClone';
src/utils/request/index.ts
@@ -120,6 +120,9 @@
        const errorInfo: ErrorInfo | undefined = (error as any).info;
        if (errorInfo) {
          const { errorMessage, errorCode } = errorInfo;
          if (Number(errorCode) === 401) {
            handleLogout();
          }
          switch (errorInfo.showType) {
            case ErrorShowType.SILENT:
              // do nothing
src/views/EmploymentManage/CheckReceiveTaskDetail.vue
@@ -32,7 +32,7 @@
              </ProFormItemV2>
            </ProFormColItem>
            <ProFormColItem :span="8">
              <ProFormItemV2 label="发布日期:">
              <ProFormItemV2 label="结束日期:">
                {{ dayjs(taskInfo.endTime ?? '').format('YYYY-MM-DD') }}
              </ProFormItemV2>
            </ProFormColItem>
src/views/FlexJobManage/FlexJobManage.vue
@@ -123,6 +123,7 @@
  defineOperationBtns,
  useFormDialog,
  UploadUserFile,
  XLSXUtils,
} from '@bole-core/components';
import { FlexJobManageColumns } from './constants';
import { EnumTaskUserHireStatusText, EnumTaskUserSignContractStatusText } from '@/constants';
@@ -312,8 +313,8 @@
    contactPhoneNumber: '',
    gender: EnumUserGender.Male,
    age: null as any as number,
    idFrontUrl: [] as UploadUserFile[],
    idBackUrl: [] as UploadUserFile[],
    identityImg: [] as UploadUserFile[],
    identityBackImg: [] as UploadUserFile[],
    contractUrl: [] as UploadUserFile[],
    regiterTime: '',
    userRealTime: '',
@@ -332,8 +333,8 @@
      contactPhoneNumber: row.contactPhoneNumber,
      gender: detail.gender,
      age: detail.age ?? null,
      idFrontUrl: convertApi2FormUrlOnlyOne(detail.identityImg),
      idBackUrl: convertApi2FormUrlOnlyOne(detail.identityBackImg),
      identityImg: convertApi2FormUrlOnlyOne(detail.identityImg),
      identityBackImg: convertApi2FormUrlOnlyOne(detail.identityBackImg),
      contractUrl: convertApi2FormUrlOnlyOne(detail.contractUrl, {
        fileName: detail.contractUrl ? detail.contractUrl.split('/').pop() : '合同',
      }),
@@ -345,7 +346,25 @@
  } catch (error) {}
}
async function handleAddOrEdit() {}
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,
@@ -354,15 +373,34 @@
} = useFormDialog({
  onConfirm: handleBatchImport,
  defaultFormParams: {
    customerId: '',
    contractTemplateId: '',
    templateDataId: '',
    url: [] as UploadUserFile[],
    userList: [],
  },
});
async function handleBatchImport() {}
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,
@@ -398,7 +436,7 @@
}
function handleDownloadTemplate() {
  downloadFileByUrl('', '批量导入模板');
  downloadFileByUrl(ImportEnterpriseEmployeesTempPath, '批量导入模板');
}
function handleBatchUnSign() {}
src/views/FlexJobManage/components/BatchImportDialog.vue
@@ -3,8 +3,8 @@
    <ProForm :model="form" ref="dialogForm" label-width="100px">
      <ProFormItemV2
        label="选择文件:"
        prop="userList"
        :check-rules="[{ message: '请上传人员名单', type: 'array' }]"
        prop="url"
        :check-rules="[{ message: '请上传人员名单', type: 'upload' }]"
      >
        <div style="display: flex">
          <ProFormUpload
@@ -12,8 +12,6 @@
            :limit="1"
            :limitFileSize="10"
            accept="xlsx,xls"
            :needUploadOss="false"
            :on-success="handleImport"
          ></ProFormUpload>
          <el-button
            type="primary"
@@ -53,11 +51,7 @@
type Form = {
  title?: string;
  customerId: string;
  contractTemplateId: string;
  templateDataId: string;
  url: UploadUserFile[];
  userList: any[];
};
const visible = defineModel({ type: Boolean });
@@ -68,8 +62,6 @@
  (e: 'onConfirm'): void;
  (e: 'onCancel'): void;
}>();
const { user } = useUser();
const dialogForm = ref<FormInstance>();
@@ -86,24 +78,6 @@
    } else {
      return;
    }
  });
}
const XLSXHeaderMap = {
  name: '姓名',
  phone: '手机号',
};
function handleImport(response: UploadUserFile) {
  XLSXUtils.resloveXLSXFromUploadInput<typeof XLSXHeaderMap>({
    //@ts-ignore
    file: response.file,
    resloveKeyList: Object.keys(XLSXHeaderMap),
    onSuccess: async (worksheetList) => {
      const userXLSXList = worksheetList[0];
      form.value.userList = userXLSXList;
      dialogForm.value?.validateField?.('userList');
    },
  });
}
</script>
src/views/FlexJobManage/components/StaffInfoDialog.vue
@@ -97,18 +97,26 @@
      </ProFormCol>
      <ProFormItemV2
        label="身份证正面:"
        prop="idFrontUrl"
        prop="identityImg"
        :check-rules="[{ message: '请上传身份证正面', type: 'upload' }]"
      >
        <ProFormImageUpload v-model:file-url="form.idFrontUrl" :limitFileSize="10" :showTip="false">
        <ProFormImageUpload
          v-model:file-url="form.identityImg"
          :limitFileSize="10"
          :showTip="false"
        >
        </ProFormImageUpload>
      </ProFormItemV2>
      <ProFormItemV2
        label="身份证反面:"
        prop="idBackUrl"
        prop="identityBackImg"
        :check-rules="[{ message: '请上传身份证反面', type: 'upload' }]"
      >
        <ProFormImageUpload v-model:file-url="form.idBackUrl" :limitFileSize="10" :showTip="false">
        <ProFormImageUpload
          v-model:file-url="form.identityBackImg"
          :limitFileSize="10"
          :showTip="false"
        >
        </ProFormImageUpload>
      </ProFormItemV2>
    </ProForm>
@@ -140,7 +148,7 @@
  ProFormUpload,
  ProFormInputNumber,
} from '@bole-core/components';
import { format } from '@/utils';
import { deepClone, format } from '@/utils';
import { EnumUserGender, EnumUserGenderTextForPerson } from '@/constants';
defineOptions({
@@ -155,8 +163,8 @@
  contactPhoneNumber: string;
  gender: EnumUserGender;
  age: number;
  idFrontUrl: UploadUserFile[];
  idBackUrl: UploadUserFile[];
  identityImg: UploadUserFile[];
  identityBackImg: UploadUserFile[];
  contractUrl: UploadUserFile[];
  regiterTime: string;
  userRealTime: string;
@@ -173,7 +181,7 @@
  visible,
  (visible) => {
    if (visible) {
      defaultForm = { ...unref(form) };
      defaultForm = deepClone(unref(form));
    }
  },
  {