yyb
10 小时以前 1678465c039ce6255105c1fcdb3ace56860f44f9
src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,345 @@
import {
  addApprovalTemplate,
  deleteApprovalTemplate,
  getApprovalTemplateDetail,
  listApprovalTemplatePage,
  TEMPLATE_TYPE_BUILTIN,
  updateApprovalTemplate,
} from "@/api/officeProcessAutomation/approvalTemplate.js";
import { Search } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { computed, reactive, ref } from "vue";
import {
  buildApprovalTemplateListParams,
  createEmptyTemplateForm,
  fetchBusinessTypeOptions,
  flowNodesSummary,
  isBuiltinTemplate,
  mapTemplateFromApi,
  mapTemplateToApi,
  nodeSignModeLabel,
  formatDisplayTime,
  unwrapTemplateDetail,
  validateTemplateForm,
} from "./approveTemplateConstants.js";
import { parseFormConfigToData } from "./formConfigUtils.js";
const FALLBACK_TEMPLATE_TYPE_OPTIONS = [
  { value: 0, label: "系统内置" },
  { value: 1, label: "自定义" },
];
function matchTemplateTypeValue(options, type) {
  if (type == null || type === "") return false;
  return options.some(
    (x) => x.value === type || x.value === Number(type) || String(x.value) === String(type)
  );
}
export function useApproveTemplate() {
  const templateTypeOptions = ref([...FALLBACK_TEMPLATE_TYPE_OPTIONS]);
  function templateTypeLabel(type) {
    if (type == null || type === "") return "—";
    const hit = templateTypeOptions.value.find(
      (x) => x.value === type || x.value === Number(type) || String(x.value) === String(type)
    );
    return hit?.label || "—";
  }
  const searchForm = reactive({
    keyword: "",
    enabledOnly: false,
  });
  const tableLoading = ref(false);
  const page = reactive({ current: 1, size: 10, total: 0 });
  const tableData = ref([]);
  const formDialog = reactive({ visible: false, title: "", mode: "add" });
  const form = reactive(createEmptyTemplateForm());
  const formRef = ref();
  const isEditingBuiltin = computed(
    () => formDialog.mode === "edit" && Number(form.templateType) === TEMPLATE_TYPE_BUILTIN
  );
  async function loadTemplateTypeOptions() {
    try {
      const list = await fetchBusinessTypeOptions();
      templateTypeOptions.value = list.length ? list : [...FALLBACK_TEMPLATE_TYPE_OPTIONS];
    } catch {
      templateTypeOptions.value = [...FALLBACK_TEMPLATE_TYPE_OPTIONS];
    }
    if (!matchTemplateTypeValue(templateTypeOptions.value, form.businessType)) {
      form.businessType = templateTypeOptions.value[0]?.value ?? "";
    }
  }
  const detailDialog = reactive({ visible: false });
  const detailRow = ref({});
  const detailLoading = ref(false);
  const formRules = {
    templateName: [{ required: true, message: "请输入模板名称", trigger: "blur" }],
    businessType: [{ required: true, message: "请选择模板类型", trigger: "change" }],
  };
  const tableColumn = ref([
    { label: "模板名称", prop: "templateName", minWidth: 140 },
    {
      label: "模板类型",
      prop: "businessType",
      width: 100,
      align: "center",
      formatData: (v) => templateTypeLabel(v),
    },
    { label: "说明", prop: "description", minWidth: 160, showOverflowTooltip: true },
    {
      label: "节点数",
      prop: "flowNodes",
      width: 80,
      align: "center",
      formatData: (v) => (Array.isArray(v) ? v.length : 0),
    },
    {
      label: "流程概要",
      prop: "flowNodes",
      minWidth: 220,
      showOverflowTooltip: true,
      formatData: (v) => flowNodesSummary(v),
    },
    {
      label: "状态",
      prop: "enabled",
      width: 90,
      align: "center",
      dataType: "tag",
      formatData: (v) => (v !== false ? "启用" : "停用"),
      formatType: (v) => (v !== false ? "success" : "info"),
    },
    {
      label: "创建时间",
      prop: "createdTime",
      width: 170,
      showOverflowTooltip: true,
      formatData: (v) => formatDisplayTime(v),
    },
    {
      label: "更新时间",
      prop: "updatedTime",
      width: 170,
      showOverflowTooltip: true,
      formatData: (v) => formatDisplayTime(v),
    },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      fixed: "right",
      width: 220,
      operation: [
        { name: "详情", type: "text", clickFun: (row) => openDetail(row) },
        { name: "编辑", type: "text", clickFun: (row) => openFormDialog("edit", row) },
        {
          name: "删除",
          type: "danger",
          link: true,
          disabled: (row) => isBuiltinTemplate(row),
          clickFun: (row) => removeTemplate(row),
        },
      ],
    },
  ]);
  async function fetchTemplateList() {
    tableLoading.value = true;
    try {
      const res = await listApprovalTemplatePage(
        buildApprovalTemplateListParams({ page, searchForm })
      );
      const data = res?.data || {};
      tableData.value = (data.records || []).map(mapTemplateFromApi);
      page.total = Number(data.total || 0);
    } catch {
      tableData.value = [];
      page.total = 0;
    } finally {
      tableLoading.value = false;
    }
  }
  function handleQuery() {
    page.current = 1;
    fetchTemplateList();
  }
  function resetSearch() {
    searchForm.keyword = "";
    searchForm.enabledOnly = false;
    handleQuery();
  }
  function pagination({ page: p, limit }) {
    page.current = p;
    page.size = limit;
    fetchTemplateList();
  }
  function resetForm(row) {
    const base = createEmptyTemplateForm();
    if (!row) {
      Object.assign(form, base);
      return;
    }
    const formConfigData = JSON.parse(
      JSON.stringify(row.formConfigData || parseFormConfigToData(row.formConfig))
    );
    const builtin = isBuiltinTemplate(row);
    Object.assign(form, {
      ...base,
      id: row.id,
      templateName: row.templateName || "",
      description: row.description || "",
      templateType: row.templateType != null ? Number(row.templateType) : base.templateType,
      businessType: row.businessType ?? "",
      formConfig: row.formConfig || "",
      formConfigData,
      lockedFormFieldUids: builtin
        ? (formConfigData.fields || []).map((f) => f._uid).filter(Boolean)
        : [],
      enabled: row.enabled !== false,
      flowNodes: JSON.parse(JSON.stringify(row.flowNodes || [base.flowNodes[0]])),
      storageBlobDTOs: JSON.parse(JSON.stringify(row.storageBlobDTOs || [])),
    });
  }
  async function openFormDialog(mode, row) {
    formDialog.mode = mode;
    formDialog.title = mode === "add" ? "新建审批模板" : "编辑审批模板";
    if (mode === "edit" && row?.id) {
      // ç¼–辑时先查询详情获取完整数据(包含附件)
      try {
        const res = await getApprovalTemplateDetail(row.id);
        const detailData = mapTemplateFromApi(unwrapTemplateDetail(res));
        resetForm(detailData);
      } catch {
        resetForm(row);
      }
    } else {
      resetForm(mode === "edit" ? row : null);
    }
    formDialog.visible = true;
  }
  async function openDetail(row) {
    if (row?.id == null || row.id === "") {
      ElMessage.warning("无法查看详情:缺少模板 ID");
      return;
    }
    detailDialog.visible = true;
    detailLoading.value = true;
    detailRow.value = {};
    try {
      const res = await getApprovalTemplateDetail(row.id);
      detailRow.value = mapTemplateFromApi(unwrapTemplateDetail(res));
    } catch {
      detailDialog.visible = false;
    } finally {
      detailLoading.value = false;
    }
  }
  async function submitForm() {
    if (!formRef.value) return false;
    try {
      await formRef.value.validate();
    } catch {
      return false;
    }
    const validated = validateTemplateForm(form);
    if (!validated.ok) {
      return { message: validated.message };
    }
    if (formDialog.mode === "edit" && !form.id) {
      return { message: "缺少模板 ID,无法保存修改" };
    }
    const dto = mapTemplateToApi(form);
    try {
      if (formDialog.mode === "add") {
        await addApprovalTemplate(dto);
      } else {
        await updateApprovalTemplate(dto);
      }
    } catch {
      return false;
    }
    formDialog.visible = false;
    page.current = 1;
    await fetchTemplateList();
    return { ok: true };
  }
  async function removeTemplate(row) {
    if (isBuiltinTemplate(row)) {
      ElMessage.warning("系统内置模板不允许删除");
      return;
    }
    if (row?.id == null || row.id === "") {
      ElMessage.warning("无法删除:缺少模板 ID");
      return;
    }
    const name = row.templateName || "未命名模板";
    try {
      await ElMessageBox.confirm(
        `确定要删除审批模板「${name}」吗?删除后不可恢复。`,
        "删除确认",
        {
          type: "warning",
          confirmButtonText: "确定删除",
          cancelButtonText: "取消",
          distinguishCancelAndClose: true,
          autofocus: false,
        }
      );
    } catch {
      return;
    }
    try {
      await deleteApprovalTemplate([row.id]);
      ElMessage.success("删除成功");
      await fetchTemplateList();
    } catch {
      /* é”™è¯¯ç”±æ‹¦æˆªå™¨æç¤º */
    }
  }
  return {
    Search,
    templateTypeOptions,
    loadTemplateTypeOptions,
    templateTypeLabel,
    fetchTemplateList,
    nodeSignModeLabel,
    flowNodesSummary,
    searchForm,
    tableLoading,
    page,
    tableData,
    tableColumn,
    formDialog,
    form,
    formRef,
    formRules,
    isEditingBuiltin,
    detailDialog,
    detailRow,
    detailLoading,
    handleQuery,
    resetSearch,
    pagination,
    openFormDialog,
    openDetail,
    submitForm,
  };
}