yyb
3 小时以前 efc0c3a697969503634138d7881543f4099b81ca
src/views/officeProcessAutomation/ApproveManage/approve-template/components/FormConfigEditor.vue
@@ -21,12 +21,20 @@
          </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>
@@ -38,7 +46,7 @@
      <el-empty
        v-if="!inner.fields.length"
        class="fce-empty"
        description="暂无填报项,可添加或从预设快速导入"
        description="暂无填报项,可添加或从已有审批模板导入"
        :image-size="72"
      />
@@ -288,14 +296,25 @@
<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,
@@ -306,6 +325,8 @@
const props = defineProps({
  modelValue: { type: Object, default: () => createEmptyFormConfigData() },
  /** 编辑当前模板时排除自身,避免从自己导入 */
  excludeTemplateId: { type: [String, Number], default: null },
});
const emit = defineEmits(["update:modelValue"]);
@@ -313,6 +334,9 @@
const inner = reactive(createEmptyFormConfigData());
const { loading: optionSourceLoading, ensureForFields, getOptions } = useSelectOptionSources();
const templateImportOptions = ref([]);
const templateImportLoading = ref(false);
function typeLabel(type) {
  return formFieldTypeLabel(type);
@@ -435,10 +459,66 @@
  emitOut();
}
function applyPreset(key) {
  const data = applyFormConfigPreset(key);
  syncFromProps(data);
  emitOut();
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>
@@ -496,6 +576,10 @@
  align-items: center;
  gap: 8px;
}
.import-tag {
  margin-left: 8px;
  vertical-align: middle;
}
.fce-empty {
  padding: 24px 0;