转正申请,调岗申请,工作交接申请,申请人可以根据配置得选项来源,选择数据
已修改9个文件
116 ■■■■ 文件已修改
src/views/officeProcessAutomation/ApproveManage/approve-list/components/FormPayloadFields.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateFormSection.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-template/selectOptionSource.js 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-template/useSelectOptionSources.js 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/HrManage/regular-apply/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/HrManage/transfer-apply/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/HrManage/work-handover/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-list/components/FormPayloadFields.vue
@@ -80,12 +80,12 @@
          clearable
          filterable
        >
          <el-option
            v-for="o in getOptions(field)"
            :key="String(o.value)"
            :label="o.label"
            :value="o.value"
          />
        <el-option
          v-for="o in getOptions(field, { moduleKey: props.moduleKey })"
          :key="String(o.value)"
          :label="o.label"
          :value="o.value"
        />
        </el-select>
        <span v-else class="field-value">{{ displayValue(field) }}</span>
      </el-form-item>
@@ -103,13 +103,14 @@
  fields: { type: Array, default: () => [] },
  formPayload: { type: Object, default: () => ({}) },
  readonly: { type: Boolean, default: false },
  moduleKey: { type: String, default: "" },
});
const { loading: optionSourceLoading, ensureForFields, getOptions, getDisplayLabel } =
  useSelectOptionSources();
async function loadOptionCaches() {
  await ensureForFields(props.fields);
  await ensureForFields(props.fields, { moduleKey: props.moduleKey });
}
onMounted(() => {
@@ -127,7 +128,7 @@
function displayValue(field) {
  const val = props.formPayload?.[field.key];
  if (field.type === "select" && field.optionSource && field.optionSource !== "static") {
    return getDisplayLabel(field, val);
    return getDisplayLabel(field, val, { moduleKey: props.moduleKey });
  }
  return formatFieldDisplayValue(field, val);
}
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue
@@ -24,6 +24,7 @@
        v-model:attachments="form.storageBlobDTOs"
        :template-attachments="form.templateAttachments"
        :user-options="userOptions"
        :module-key="moduleKey"
        :show-template-name="!isEdit"
        :allow-change-template="false"
        :flow-attachments-only="flowAttachmentsOnly"
@@ -56,6 +57,7 @@
  fields: { type: Array, default: () => [] },
  activeTemplate: { type: Object, default: null },
  userOptions: { type: Array, default: () => [] },
  moduleKey: { type: String, default: "" },
  isEdit: { type: Boolean, default: false },
  saving: { type: Boolean, default: false },
  formRef: { type: Object, default: null },
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue
@@ -4,7 +4,7 @@
  用法:
  <ApprovalTemplateBindDialog
    v-model:visible="visible"
    module-key="regular"
    :module-key="APPROVAL_MODULE_KEYS.REGULAR"
    @confirm="onTemplateBound"
  />
-->
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateFormSection.vue
@@ -15,6 +15,7 @@
      v-if="!hideFormFields && !flowAttachmentsOnly && !flowOnly"
      :fields="fields"
      :form-payload="formPayload"
      :module-key="moduleKey"
    />
    <el-form-item label="审批流程" required>
@@ -87,6 +88,7 @@
  uploadLimit: { type: Number, default: 10 },
  /** 为 true 时可编辑模板预置的审批人(仅审批模板管理页使用) */
  flowEditable: { type: Boolean, default: false },
  moduleKey: { type: String, default: "" },
});
const emit = defineEmits(["update:flowNodes", "update:attachments", "change-template"]);
src/views/officeProcessAutomation/ApproveManage/approve-template/selectOptionSource.js
@@ -1,30 +1,42 @@
import { deptTreeSelect, userListNoPageByTenantId } from "@/api/system/user.js";
import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
/** 下拉选项来源(写入 formConfig,提交页按来源拉取数据) */
export const SELECT_OPTION_SOURCE = {
  STATIC: "static",
  USER: "user",
  DEPT: "dept",
  EMPLOYEE: "employee",
};
export const SELECT_OPTION_SOURCE_OPTIONS = [
  { value: SELECT_OPTION_SOURCE.STATIC, label: "手动配置", desc: "在模板中自定义选项文本与值" },
  { value: SELECT_OPTION_SOURCE.USER, label: "人员列表", desc: "从系统用户中选择,值为用户 ID" },
  { value: SELECT_OPTION_SOURCE.DEPT, label: "部门列表", desc: "从组织架构中选择,值为部门 ID" },
  { value: SELECT_OPTION_SOURCE.EMPLOYEE, label: "员工列表", desc: "从在职员工中选择,值为员工 ID" },
];
const EMPLOYEE_APPLICANT_MODULE_KEYS = new Set(["regular"]);
export function selectOptionSourceLabel(source) {
  return SELECT_OPTION_SOURCE_OPTIONS.find((x) => x.value === source)?.label || "—";
}
export function isDynamicOptionSource(source) {
  return source === SELECT_OPTION_SOURCE.USER || source === SELECT_OPTION_SOURCE.DEPT;
  return (
    source === SELECT_OPTION_SOURCE.USER ||
    source === SELECT_OPTION_SOURCE.DEPT ||
    source === SELECT_OPTION_SOURCE.EMPLOYEE
  );
}
function unwrapArray(payload) {
  if (Array.isArray(payload)) return payload;
  if (Array.isArray(payload?.records)) return payload.records;
  if (payload?.data && Array.isArray(payload.data)) return payload.data;
  if (Array.isArray(payload?.data?.records)) return payload.data.records;
  if (payload?.rows && Array.isArray(payload.rows)) return payload.rows;
  if (Array.isArray(payload?.data?.rows)) return payload.data.rows;
  return [];
}
@@ -39,6 +51,15 @@
  const value = u.userId ?? u.id;
  return {
    label: u.nickName || u.userName || `用户${value}`,
    value,
  };
}
/** 在职员工 → 下拉 option */
export function mapEmployeeToSelectOption(u) {
  const value = u.id ?? u.staffOnJobId ?? u.staffId;
  return {
    label: u.staffName || u.name || u.userName || `员工${value}`,
    value,
  };
}
@@ -70,21 +91,41 @@
}
/** 按字段配置解析下拉 options(需传入已加载的缓存) */
export function resolveFieldSelectOptions(field, caches = {}) {
function isApplicantField(field) {
  const key = String(field?.key || "").toLowerCase();
  const label = String(field?.label || "");
  return (
    key === "applicant" ||
    key === "applicantname" ||
    label.includes("申请人")
  );
}
export function resolveFieldSelectOptions(field, caches = {}, context = {}) {
  const source = field?.optionSource || SELECT_OPTION_SOURCE.STATIC;
  if (
    source === SELECT_OPTION_SOURCE.USER &&
    EMPLOYEE_APPLICANT_MODULE_KEYS.has(context.moduleKey) &&
    isApplicantField(field)
  ) {
    return (caches.employees || []).map(mapEmployeeToSelectOption);
  }
  if (source === SELECT_OPTION_SOURCE.USER) {
    return (caches.users || []).map(mapUserToSelectOption);
  }
  if (source === SELECT_OPTION_SOURCE.DEPT) {
    return caches.deptOptions || [];
  }
  if (source === SELECT_OPTION_SOURCE.EMPLOYEE) {
    return (caches.employees || []).map(mapEmployeeToSelectOption);
  }
  return (field?.options || []).filter((o) => o.value !== "" && o.value != null);
}
/** 根据已解析的 options 反查展示文本 */
export function resolveSelectDisplayLabel(field, val, caches = {}) {
export function resolveSelectDisplayLabel(field, val, caches = {}, context = {}) {
  if (val == null || val === "") return "—";
  const options = resolveFieldSelectOptions(field, caches);
  const options = resolveFieldSelectOptions(field, caches, context);
  const hit = options.find((o) => String(o.value) === String(val));
  return hit?.label || String(val);
}
@@ -93,9 +134,10 @@
export async function fetchSelectOptionCaches(sources = []) {
  const needUser = sources.includes(SELECT_OPTION_SOURCE.USER);
  const needDept = sources.includes(SELECT_OPTION_SOURCE.DEPT);
  const caches = { users: [], deptOptions: [] };
  const needEmployee = sources.includes(SELECT_OPTION_SOURCE.EMPLOYEE);
  const caches = { users: [], deptOptions: [], employees: [] };
  if (!needUser && !needDept) return caches;
  if (!needUser && !needDept && !needEmployee) return caches;
  const tasks = [];
  if (needUser) {
@@ -123,17 +165,36 @@
        })
    );
  }
  if (needEmployee) {
    tasks.push(
      staffOnJobListPage({ current: -1, size: -1, staffState: 1 })
        .then((res) => {
          caches.employees = unwrapArray(res);
        })
        .catch(() => {
          caches.employees = [];
        })
    );
  }
  await Promise.all(tasks);
  return caches;
}
/** 从字段列表收集需要预加载的动态来源 */
export function collectOptionSourcesFromFields(fields) {
export function collectOptionSourcesFromFields(fields, context = {}) {
  const set = new Set();
  (fields || []).forEach((f) => {
    if (f?.type === "select" && isDynamicOptionSource(f.optionSource)) {
      set.add(f.optionSource);
      if (
        EMPLOYEE_APPLICANT_MODULE_KEYS.has(context.moduleKey) &&
        f.optionSource === SELECT_OPTION_SOURCE.USER &&
        isApplicantField(f)
      ) {
        set.add(SELECT_OPTION_SOURCE.EMPLOYEE);
      } else {
        set.add(f.optionSource);
      }
    }
  });
  return [...set];
src/views/officeProcessAutomation/ApproveManage/approve-template/useSelectOptionSources.js
@@ -14,25 +14,26 @@
    deptOptions: [],
  });
  async function ensureForFields(fields) {
    const sources = collectOptionSourcesFromFields(fields);
  async function ensureForFields(fields, context = {}) {
    const sources = collectOptionSourcesFromFields(fields, context);
    if (!sources.length) return;
    loading.value = true;
    try {
      const next = await fetchSelectOptionCaches(sources);
      caches.users = next.users;
      caches.deptOptions = next.deptOptions;
      caches.employees = next.employees || [];
    } finally {
      loading.value = false;
    }
  }
  function getOptions(field) {
    return resolveFieldSelectOptions(field, caches);
  function getOptions(field, context = {}) {
    return resolveFieldSelectOptions(field, caches, context);
  }
  function getDisplayLabel(field, val) {
    return resolveSelectDisplayLabel(field, val, caches);
  function getDisplayLabel(field, val, context = {}) {
    return resolveSelectDisplayLabel(field, val, caches, context);
  }
  return {
src/views/officeProcessAutomation/HrManage/regular-apply/index.vue
@@ -48,6 +48,7 @@
      :fields="submitFormFields"
      :active-template="activeTemplate"
      :user-options="flowUserOptions"
      :module-key="APPROVAL_MODULE_KEYS.REGULAR"
      :is-edit="isSubmitEdit"
      :saving="submitSaving"
      :form-ref="submitFormRef"
src/views/officeProcessAutomation/HrManage/transfer-apply/index.vue
@@ -58,6 +58,7 @@
      :fields="submitFormFields"
      :active-template="activeTemplate"
      :user-options="flowUserOptions"
      :module-key="APPROVAL_MODULE_KEYS.TRANSFER"
      :is-edit="isSubmitEdit"
      :saving="submitSaving"
      :form-ref="submitFormRef"
src/views/officeProcessAutomation/HrManage/work-handover/index.vue
@@ -58,6 +58,7 @@
      :fields="submitFormFields"
      :active-template="activeTemplate"
      :user-options="flowUserOptions"
      :module-key="APPROVAL_MODULE_KEYS.WORK_HANDOVER"
      :is-edit="isSubmitEdit"
      :saving="submitSaving"
      :form-ref="submitFormRef"