| | |
| | | placeholder="选填" |
| | | style="width: 100%" |
| | | clearable |
| | | filterable |
| | | :loading="optionSourceLoading" |
| | | @change="emitOut" |
| | | > |
| | | <el-option |
| | | v-for="o in field.options.filter((x) => x.value !== '' && x.value != null)" |
| | | v-for="o in resolvedSelectOptions(field)" |
| | | :key="String(o.value)" |
| | | :label="o.label || o.value" |
| | | :value="o.value" |
| | |
| | | </div> |
| | | |
| | | <div v-if="field.type === 'select'" class="fce-section fce-section--options"> |
| | | <div class="fce-options-head"> |
| | | <span class="fce-section-title">下拉选项</span> |
| | | <el-row :gutter="16" class="fce-source-row"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="选项来源" class="fce-field-item"> |
| | | <el-select |
| | | v-model="field.optionSource" |
| | | style="width: 100%" |
| | | @change="onOptionSourceChange(field)" |
| | | > |
| | | <el-option |
| | | v-for="s in SELECT_OPTION_SOURCE_OPTIONS" |
| | | :key="s.value" |
| | | :label="s.label" |
| | | :value="s.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <p v-if="isDynamicOptionSource(field.optionSource)" class="fce-source-tip"> |
| | | {{ optionSourceDesc(field.optionSource) }}。提交审批时将自动加载最新数据,无需手动维护选项。 |
| | | </p> |
| | | <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> |
| | |
| | | @click="removeOption(field, oi)" |
| | | /> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | createEmptyFormField, |
| | | formFieldTypeLabel, |
| | | } from "../formConfigUtils.js"; |
| | | import { |
| | | SELECT_OPTION_SOURCE, |
| | | SELECT_OPTION_SOURCE_OPTIONS, |
| | | isDynamicOptionSource, |
| | | } from "../selectOptionSource.js"; |
| | | import { useSelectOptionSources } from "../useSelectOptionSources.js"; |
| | | |
| | | const props = defineProps({ |
| | | modelValue: { type: Object, default: () => createEmptyFormConfigData() }, |
| | |
| | | const emit = defineEmits(["update:modelValue"]); |
| | | |
| | | const inner = reactive(createEmptyFormConfigData()); |
| | | |
| | | const { loading: optionSourceLoading, ensureForFields, getOptions } = useSelectOptionSources(); |
| | | |
| | | function typeLabel(type) { |
| | | return formFieldTypeLabel(type); |
| | |
| | | return `选填,选择模板时将预填${name}`; |
| | | } |
| | | |
| | | function optionSourceDesc(source) { |
| | | return SELECT_OPTION_SOURCE_OPTIONS.find((x) => x.value === source)?.desc || ""; |
| | | } |
| | | |
| | | function resolvedSelectOptions(field) { |
| | | if (field.type !== "select") return []; |
| | | return getOptions(field); |
| | | } |
| | | |
| | | function syncFromProps(v) { |
| | | const src = v || createEmptyFormConfigData(); |
| | | inner.summaryPlaceholder = src.summaryPlaceholder || ""; |
| | |
| | | ...createEmptyFormField(), |
| | | ...f, |
| | | _uid: f._uid || createEmptyFormField()._uid, |
| | | optionSource: f.optionSource || SELECT_OPTION_SOURCE.STATIC, |
| | | options: (f.options || [{ label: "", value: "" }]).map((o) => ({ ...o })), |
| | | })); |
| | | ensureForFields(inner.fields); |
| | | } |
| | | |
| | | function emitOut() { |
| | |
| | | min: f.min, |
| | | precision: f.precision, |
| | | defaultValue: cloneDefaultValue(f), |
| | | optionSource: f.optionSource || SELECT_OPTION_SOURCE.STATIC, |
| | | options: (f.options || []).map((o) => ({ label: o.label, value: o.value })), |
| | | })), |
| | | }); |
| | |
| | | |
| | | function addField() { |
| | | inner.fields.push(createEmptyFormField()); |
| | | ensureForFields(inner.fields); |
| | | emitOut(); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | function onTypeChange(field) { |
| | | if (field.type === "select" && (!field.options || !field.options.length)) { |
| | | if (field.type === "select") { |
| | | if (!field.optionSource) field.optionSource = SELECT_OPTION_SOURCE.STATIC; |
| | | if (!field.options || !field.options.length) { |
| | | field.options = [{ label: "", value: "" }]; |
| | | } |
| | | ensureForFields(inner.fields); |
| | | } |
| | | resetDefaultValueForType(field); |
| | | emitOut(); |
| | | } |
| | | |
| | | function onOptionSourceChange(field) { |
| | | field.defaultValue = ""; |
| | | if (!isDynamicOptionSource(field.optionSource) && (!field.options || !field.options.length)) { |
| | | field.options = [{ label: "", value: "" }]; |
| | | } |
| | | ensureForFields(inner.fields); |
| | | emitOut(); |
| | | } |
| | | |
| | |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .fce-options-head .fce-section-title { |
| | | .fce-options-head .fce-section-title, |
| | | .fce-options-head .fce-section-subtitle { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .fce-section-subtitle { |
| | | font-size: 12px; |
| | | font-weight: 600; |
| | | color: var(--el-text-color-secondary); |
| | | } |
| | | |
| | | .fce-source-row { |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .fce-source-tip { |
| | | margin: 0 0 10px; |
| | | font-size: 12px; |
| | | color: var(--el-text-color-secondary); |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .fce-option-row { |
| | | display: flex; |
| | | align-items: center; |