fix(bpm/hrm): 修复流程发起人搜索、流程管理员默认超管;核算新增批量删除

协同办公 - 流程模型:
1. 发起选择人搜索不可用:原来只把输入传给 username(登录账号),
输入中文姓名搜不到;且前端 filterOption 会二次过滤当前页数据。
改为传 keyword(后端按「账号 OR 姓名」模糊匹配),filterOption 恒 true 交给后端。
2. 新建流程模型时流程管理员默认取超级管理员(admin),
原来默认取当前登录用户(普通账号新建时会把自己设为管理员)。

薪酬管理 - 薪资核算:
3. 新增「批量删除」按钮:全选后一键删除,不限制状态(勾选即删),
删除前二次确认,删除后刷新列表。
已修改4个文件
67 ■■■■■ 文件已修改
src/api/hrm/salary/calculation/index.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/hrm/salary/calculation/index.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/user/components/select-modal.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/hrm/salary/calculation/index.ts
@@ -124,6 +124,13 @@
  return requestClient.delete(`/hrm/salary/calculation/delete?id=${id}`);
}
/** 批量删除薪酬核算记录(不限制状态,勾选即删) */
export function deleteSalaryCalculationBatch(ids: number[]) {
  return requestClient.delete<number>(
    `/hrm/salary/calculation/delete-batch?ids=${ids.join(',')}`,
  );
}
/** 导出薪酬核算表 */
export function exportSalaryCalculation(params: any) {
  return requestClient.download('/hrm/salary/calculation/export-excel', { params });
src/views/bpm/model/form/index.vue
@@ -188,7 +188,7 @@
  } else {
    // 情况三:新增场景
    formData.value.startUserType = 0; // 全体
    formData.value.managerUserIds.push(userStore.userInfo?.id);
    // 流程管理员默认值稍后设置(需要先加载用户列表才能定位超级管理员)
  }
  // 获取表单列表
@@ -199,6 +199,17 @@
  // 获取部门列表
  deptList.value = await getSimpleDeptList();
  // 新增场景(流程管理员还没值时)默认取超级管理员(admin),而不是当前登录用户
  if (!formData.value.managerUserIds?.length) {
    const adminUser = userList.value.find(
      (user: SystemUserApi.User) => user.username === 'admin',
    );
    const defaultManagerId = adminUser?.id ?? userStore.userInfo?.id;
    if (defaultManagerId) {
      formData.value.managerUserIds = [defaultManagerId];
    }
  }
  // 最终,设置 currentStep 切换到第一步
  currentStep.value = 0;
  // 以前未配置更多设置的流程
src/views/hrm/salary/calculation/index.vue
@@ -17,6 +17,7 @@
  calculateSalary,
  confirmSalary,
  deleteSalaryCalculation,
  deleteSalaryCalculationBatch,
  exportSalaryCalculation,
  getSalaryCalculationPage,
  previewSalaryCalculation,
@@ -189,6 +190,37 @@
  const ids = records.map((r) => r.id!);
  await confirmSalary(ids);
  message.success('确认成功');
  handleRefresh();
}
/** 批量删除选中的核算记录(不限制状态,勾选即删) */
async function handleBatchDelete() {
  const records = gridApi.grid.getCheckboxRecords() as HrmSalaryCalculationApi.SalaryCalculation[];
  if (records.length === 0) {
    message.warning('请选择要删除的核算记录');
    return;
  }
  const ids = records.map((r) => r.id!).filter(Boolean);
  if (ids.length === 0) {
    message.warning('选中的记录缺少 ID,请刷新后重试');
    return;
  }
  const confirmed = await new Promise<boolean>((resolve) => {
    Modal.confirm({
      title: '确认批量删除',
      content: `确定删除选中的 ${ids.length} 条核算记录吗?删除后需重新核算,且不可恢复。`,
      okText: '确定删除',
      okType: 'danger',
      cancelText: '取消',
      onOk: () => resolve(true),
      onCancel: () => resolve(false),
    });
  });
  if (!confirmed) {
    return;
  }
  const count = await deleteSalaryCalculationBatch(ids);
  message.success(`已删除 ${count ?? ids.length} 条核算记录`);
  handleRefresh();
}
@@ -611,6 +643,12 @@
              onClick: handleBatchSave,
            },
            {
              label: '批量删除',
              danger: true,
              auth: ['hrm:salary-calculation:delete'],
              onClick: handleBatchDelete,
            },
            {
              label: '保存修改',
              type: 'primary',
              auth: ['hrm:salary-calculation:calculate'],
src/views/system/user/components/select-modal.vue
@@ -193,7 +193,8 @@
      pageNo,
      pageSize,
      deptId: selectedDeptId.value,
      username: leftListState.value.searchValue || undefined,
      // 传 keyword:后端同时按「账号」和「姓名」模糊匹配(原来只传 username,中文姓名搜不到)
      keyword: leftListState.value.searchValue?.trim() || undefined,
    });
    leftListState.value.dataSource = list;
@@ -310,8 +311,10 @@
}
// TODO   后端接口目前仅支持  username 检索, 筛选条件需要跟后端请求参数保持一致。
function filterOption(inputValue: string, option: any) {
  return option.username.toLowerCase().includes(inputValue.toLowerCase());
function filterOption(_inputValue: string, _option: any) {
  // 搜索由后端完成(keyword 同时匹配账号与姓名),这里恒返回 true,
  // 否则前端只会过滤当前页 dataSource,导致搜不到其他页/其他用户的记录
  return true;
}
/** 处理部门树展开/折叠 */