| | |
| | | </el-tag> |
| | | </div> |
| | | <div class="fce-toolbar-actions"> |
| | | <el-dropdown trigger="click" @command="applyPreset"> |
| | | <el-button size="small">从预设导入</el-button> |
| | | <el-dropdown trigger="click" @visible-change="onImportDropdownVisible" @command="importFromTemplate"> |
| | | <el-button size="small" :loading="templateImportLoading">从已有模板导入</el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item v-for="p in FORM_CONFIG_PRESETS" :key="p.key" :command="p.key"> |
| | | {{ p.label }} |
| | | <el-dropdown-item v-if="!templateImportOptions.length" disabled> |
| | | 暂无其他审批模板 |
| | | </el-dropdown-item> |
| | | <el-dropdown-item |
| | | v-for="t in templateImportOptions" |
| | | :key="t.id" |
| | | :command="t.id" |
| | | > |
| | | <span>{{ t.label }}</span> |
| | | <el-tag v-if="!t.enabled" size="small" type="info" class="import-tag">已停用</el-tag> |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | |
| | | <el-empty |
| | | v-if="!inner.fields.length" |
| | | class="fce-empty" |
| | | description="暂无填报项,可添加或从预设快速导入" |
| | | description="暂无填报项,可添加或从已有审批模板导入" |
| | | :image-size="72" |
| | | /> |
| | | |
| | |
| | | |
| | | <script setup> |
| | | import { Bottom, Delete, Plus, Top } from "@element-plus/icons-vue"; |
| | | import { reactive, watch } from "vue"; |
| | | import { |
| | | FORM_CONFIG_PRESETS, |
| | | getApprovalTemplateDetail, |
| | | listApprovalTemplate, |
| | | TEMPLATE_TYPE_BUILTIN, |
| | | TEMPLATE_TYPE_CUSTOM, |
| | | } from "@/api/officeProcessAutomation/approvalTemplate.js"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { reactive, ref, watch } from "vue"; |
| | | import { |
| | | mapEnabledFromApi, |
| | | unwrapTemplateDetail, |
| | | unwrapTemplateList, |
| | | } from "../approveTemplateConstants.js"; |
| | | import { |
| | | FORM_FIELD_TYPE_OPTIONS, |
| | | applyFormConfigPreset, |
| | | createEmptyFormConfigData, |
| | | createEmptyFormField, |
| | | formFieldTypeLabel, |
| | | parseFormConfigToData, |
| | | } from "../formConfigUtils.js"; |
| | | import { |
| | | SELECT_OPTION_SOURCE, |
| | |
| | | |
| | | const props = defineProps({ |
| | | modelValue: { type: Object, default: () => createEmptyFormConfigData() }, |
| | | /** 编辑当前模板时排除自身,避免从自己导入 */ |
| | | excludeTemplateId: { type: [String, Number], default: null }, |
| | | }); |
| | | |
| | | const emit = defineEmits(["update:modelValue"]); |
| | |
| | | const inner = reactive(createEmptyFormConfigData()); |
| | | |
| | | const { loading: optionSourceLoading, ensureForFields, getOptions } = useSelectOptionSources(); |
| | | |
| | | const templateImportOptions = ref([]); |
| | | const templateImportLoading = ref(false); |
| | | |
| | | function typeLabel(type) { |
| | | return formFieldTypeLabel(type); |
| | |
| | | emitOut(); |
| | | } |
| | | |
| | | function applyPreset(key) { |
| | | const data = applyFormConfigPreset(key); |
| | | async function loadTemplateImportOptions() { |
| | | templateImportLoading.value = true; |
| | | try { |
| | | const [customRes, builtinRes] = await Promise.all([ |
| | | listApprovalTemplate(TEMPLATE_TYPE_CUSTOM), |
| | | listApprovalTemplate(TEMPLATE_TYPE_BUILTIN), |
| | | ]); |
| | | const excludeId = |
| | | props.excludeTemplateId != null && props.excludeTemplateId !== "" |
| | | ? String(props.excludeTemplateId) |
| | | : ""; |
| | | templateImportOptions.value = [...unwrapTemplateList(customRes), ...unwrapTemplateList(builtinRes)] |
| | | .filter((row) => row?.id != null && String(row.id) !== excludeId) |
| | | .map((row) => ({ |
| | | id: row.id, |
| | | label: row.templateName || `模板 #${row.id}`, |
| | | enabled: mapEnabledFromApi(row.enabled), |
| | | })); |
| | | } catch { |
| | | templateImportOptions.value = []; |
| | | ElMessage.error("加载审批模板列表失败"); |
| | | } finally { |
| | | templateImportLoading.value = false; |
| | | } |
| | | } |
| | | |
| | | function onImportDropdownVisible(visible) { |
| | | if (visible) loadTemplateImportOptions(); |
| | | } |
| | | |
| | | async function importFromTemplate(templateId) { |
| | | if (!templateId) return; |
| | | if (inner.fields.length) { |
| | | try { |
| | | await ElMessageBox.confirm("将覆盖当前填报项配置,是否继续?", "从模板导入", { |
| | | type: "warning", |
| | | confirmButtonText: "继续导入", |
| | | cancelButtonText: "取消", |
| | | }); |
| | | } catch { |
| | | return; |
| | | } |
| | | } |
| | | templateImportLoading.value = true; |
| | | try { |
| | | const res = await getApprovalTemplateDetail(templateId); |
| | | const row = unwrapTemplateDetail(res); |
| | | const data = parseFormConfigToData(row?.formConfig); |
| | | if (!data.fields?.length) { |
| | | ElMessage.warning("该模板未配置填报项"); |
| | | return; |
| | | } |
| | | syncFromProps(data); |
| | | emitOut(); |
| | | ElMessage.success(`已导入「${row.templateName || "模板"}」的填报项`); |
| | | } catch { |
| | | ElMessage.error("加载模板详情失败"); |
| | | } finally { |
| | | templateImportLoading.value = false; |
| | | } |
| | | } |
| | | </script> |
| | | |
| | |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | .import-tag { |
| | | margin-left: 8px; |
| | | vertical-align: middle; |
| | | } |
| | | |
| | | .fce-empty { |
| | | padding: 24px 0; |