| | |
| | | </el-tag> |
| | | </div> |
| | | <div class="fce-toolbar-actions"> |
| | | <el-dropdown trigger="click" @visible-change="onImportDropdownVisible" @command="importFromTemplate"> |
| | | <el-button size="small" :loading="templateImportLoading">从已有模板导入</el-button> |
| | | <el-dropdown |
| | | trigger="click" |
| | | :disabled="disableImport" |
| | | @visible-change="onImportDropdownVisible" |
| | | @command="importFromTemplate" |
| | | > |
| | | <el-button size="small" :loading="templateImportLoading" :disabled="disableImport"> |
| | | 从已有模板导入 |
| | | </el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item v-if="!templateImportOptions.length" disabled> |
| | |
| | | v-for="(field, index) in inner.fields" |
| | | :key="field._uid" |
| | | class="fce-card" |
| | | :class="{ 'fce-card--required': field.required }" |
| | | :class="{ |
| | | 'fce-card--required': field.required, |
| | | 'fce-card--locked': isFieldLocked(field), |
| | | }" |
| | | > |
| | | <div class="fce-card-badge">{{ index + 1 }}</div> |
| | | |
| | |
| | | <span class="fce-card-name">{{ field.label || `填报项 ${index + 1}` }}</span> |
| | | <el-tag size="small" effect="light" type="primary">{{ typeLabel(field.type) }}</el-tag> |
| | | <el-tag v-if="field.required" size="small" type="danger" effect="plain">必填</el-tag> |
| | | <el-tag v-if="isFieldLocked(field)" size="small" type="info" effect="plain">内置项</el-tag> |
| | | </div> |
| | | <div class="fce-card-btns"> |
| | | <div v-if="!isFieldLocked(field)" class="fce-card-btns"> |
| | | <el-tooltip content="上移" placement="top"> |
| | | <el-button circle size="small" :disabled="index === 0" @click="moveField(index, -1)"> |
| | | <el-icon><Top /></el-icon> |
| | |
| | | v-model="field.label" |
| | | placeholder="如:报销说明" |
| | | maxlength="50" |
| | | :disabled="isFieldLocked(field)" |
| | | @input="emitOut" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="字段标识" required class="fce-field-item"> |
| | | <el-input v-model="field.key" placeholder="如:summary" maxlength="50" @input="emitOut" /> |
| | | <el-input |
| | | v-model="field.key" |
| | | placeholder="如:summary" |
| | | maxlength="50" |
| | | :disabled="isFieldLocked(field)" |
| | | @input="emitOut" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="控件类型" class="fce-field-item"> |
| | | <el-select v-model="field.type" style="width: 100%" @change="onTypeChange(field)"> |
| | | <el-select |
| | | v-model="field.type" |
| | | style="width: 100%" |
| | | :disabled="isFieldLocked(field)" |
| | | @change="onTypeChange(field)" |
| | | > |
| | | <el-option |
| | | v-for="t in FORM_FIELD_TYPE_OPTIONS" |
| | | :key="t.value" |
| | |
| | | inline-prompt |
| | | active-text="必填" |
| | | inactive-text="选填" |
| | | :disabled="isFieldLocked(field)" |
| | | @change="emitOut" |
| | | /> |
| | | </el-form-item> |
| | |
| | | :max="10" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="isFieldLocked(field)" |
| | | @change="emitOut" |
| | | /> |
| | | </el-form-item> |
| | |
| | | v-model="field.min" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="isFieldLocked(field)" |
| | | @change="emitOut" |
| | | /> |
| | | </el-form-item> |
| | |
| | | :max="4" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="isFieldLocked(field)" |
| | | @change="emitOut" |
| | | /> |
| | | </el-form-item> |
| | |
| | | :type="field.type === 'textarea' ? 'textarea' : 'text'" |
| | | :rows="field.type === 'textarea' ? 2 : undefined" |
| | | :placeholder="defaultPlaceholder(field)" |
| | | :disabled="isFieldLocked(field)" |
| | | clearable |
| | | @input="emitOut" |
| | | /> |
| | |
| | | controls-position="right" |
| | | placeholder="选填" |
| | | style="width: 100%" |
| | | :disabled="isFieldLocked(field)" |
| | | @change="emitOut" |
| | | /> |
| | | <el-date-picker |
| | |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | :disabled="isFieldLocked(field)" |
| | | clearable |
| | | @change="emitOut" |
| | | /> |
| | |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | style="width: 100%" |
| | | :disabled="isFieldLocked(field)" |
| | | clearable |
| | | @change="emitOut" |
| | | /> |
| | |
| | | clearable |
| | | filterable |
| | | :loading="optionSourceLoading" |
| | | :disabled="isFieldLocked(field)" |
| | | @change="emitOut" |
| | | > |
| | | <el-option |
| | |
| | | <el-select |
| | | v-model="field.optionSource" |
| | | style="width: 100%" |
| | | :disabled="isFieldLocked(field)" |
| | | @change="onOptionSourceChange(field)" |
| | | > |
| | | <el-option |
| | |
| | | <template v-if="!isDynamicOptionSource(field.optionSource)"> |
| | | <div class="fce-options-head"> |
| | | <span class="fce-section-subtitle">手动选项</span> |
| | | <el-button type="primary" link size="small" :icon="Plus" @click="addOption(field)"> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | size="small" |
| | | :icon="Plus" |
| | | :disabled="isFieldLocked(field)" |
| | | @click="addOption(field)" |
| | | > |
| | | 添加选项 |
| | | </el-button> |
| | | </div> |
| | |
| | | class="fce-option-row" |
| | | > |
| | | <span class="fce-option-index">{{ oi + 1 }}</span> |
| | | <el-input v-model="opt.label" placeholder="显示文本" @input="emitOut" /> |
| | | <el-input v-model="opt.value" placeholder="选项值" class="fce-option-value" @input="emitOut" /> |
| | | <el-input |
| | | v-model="opt.label" |
| | | placeholder="显示文本" |
| | | :disabled="isFieldLocked(field)" |
| | | @input="emitOut" |
| | | /> |
| | | <el-input |
| | | v-model="opt.value" |
| | | placeholder="选项值" |
| | | class="fce-option-value" |
| | | :disabled="isFieldLocked(field)" |
| | | @input="emitOut" |
| | | /> |
| | | <el-button |
| | | type="danger" |
| | | link |
| | | :icon="Delete" |
| | | :disabled="field.options.length <= 1" |
| | | :disabled="isFieldLocked(field) || field.options.length <= 1" |
| | | @click="removeOption(field, oi)" |
| | | /> |
| | | </div> |
| | |
| | | TEMPLATE_TYPE_CUSTOM, |
| | | } from "@/api/officeProcessAutomation/approvalTemplate.js"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { reactive, ref, watch } from "vue"; |
| | | import { computed, reactive, ref, watch } from "vue"; |
| | | import { |
| | | mapEnabledFromApi, |
| | | unwrapTemplateDetail, |
| | |
| | | modelValue: { type: Object, default: () => createEmptyFormConfigData() }, |
| | | /** 编辑当前模板时排除自身,避免从自己导入 */ |
| | | excludeTemplateId: { type: [String, Number], default: null }, |
| | | /** 禁用「从已有模板导入」 */ |
| | | disableImport: { type: Boolean, default: false }, |
| | | /** 系统内置模板编辑时,打开弹窗即存在的填报项 _uid,不可改删 */ |
| | | lockedFieldUids: { type: Array, default: () => [] }, |
| | | }); |
| | | |
| | | const emit = defineEmits(["update:modelValue"]); |
| | |
| | | |
| | | const templateImportOptions = ref([]); |
| | | const templateImportLoading = ref(false); |
| | | |
| | | const lockedUidSet = computed( |
| | | () => new Set((props.lockedFieldUids || []).filter(Boolean)) |
| | | ); |
| | | |
| | | function isFieldLocked(field) { |
| | | return field?._uid != null && lockedUidSet.value.has(field._uid); |
| | | } |
| | | |
| | | function typeLabel(type) { |
| | | return formFieldTypeLabel(type); |
| | |
| | | } |
| | | |
| | | function removeField(index) { |
| | | if (isFieldLocked(inner.fields[index])) return; |
| | | inner.fields.splice(index, 1); |
| | | emitOut(); |
| | | } |
| | | |
| | | function moveField(index, delta) { |
| | | if (isFieldLocked(inner.fields[index])) return; |
| | | const next = index + delta; |
| | | if (next < 0 || next >= inner.fields.length) return; |
| | | if (isFieldLocked(inner.fields[next])) return; |
| | | const t = inner.fields[index]; |
| | | inner.fields[index] = inner.fields[next]; |
| | | inner.fields[next] = t; |
| | |
| | | } |
| | | |
| | | function onImportDropdownVisible(visible) { |
| | | if (props.disableImport) return; |
| | | if (visible) loadTemplateImportOptions(); |
| | | } |
| | | |
| | |
| | | border-left: 3px solid var(--el-color-danger-light-3); |
| | | } |
| | | |
| | | .fce-card--locked { |
| | | background: var(--el-fill-color-light); |
| | | } |
| | | |
| | | .fce-card-badge { |
| | | position: absolute; |
| | | top: -10px; |