| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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, |
| | | }; |
| | | } |