<!-- 填报项:编辑为表单控件,详情为 descriptions 表格(与上方基础信息一致) -->
|
<template>
|
<template v-if="fields?.length">
|
<el-descriptions
|
v-if="readonly"
|
:column="2"
|
border
|
class="form-payload-desc"
|
>
|
<el-descriptions-item
|
v-for="field in fields"
|
:key="field.key"
|
:label="field.label"
|
:span="field.type === 'textarea' || field.type === 'datetimerange' ? 2 : 1"
|
>
|
<span class="field-value">{{ displayValue(field) }}</span>
|
</el-descriptions-item>
|
</el-descriptions>
|
|
<div
|
v-else
|
class="form-payload-edit"
|
v-loading="optionSourceLoading"
|
>
|
<el-form-item
|
v-for="field in fields"
|
:key="field.key"
|
:label="field.label"
|
:prop="`formPayload.${field.key}`"
|
:required="Boolean(field.required)"
|
>
|
<el-input
|
v-if="field.type === 'text'"
|
v-model="formPayload[field.key]"
|
:placeholder="`请输入${field.label}`"
|
maxlength="200"
|
/>
|
<el-input
|
v-else-if="field.type === 'textarea'"
|
v-model="formPayload[field.key]"
|
type="textarea"
|
:rows="field.rows || 3"
|
:placeholder="`请填写${field.label}`"
|
maxlength="2000"
|
show-word-limit
|
/>
|
<el-input-number
|
v-else-if="field.type === 'number'"
|
v-model="formPayload[field.key]"
|
:min="field.min ?? 0"
|
:precision="field.precision ?? 0"
|
controls-position="right"
|
style="width: 100%"
|
/>
|
<el-date-picker
|
v-else-if="field.type === 'date'"
|
v-model="formPayload[field.key]"
|
type="date"
|
:placeholder="`请选择${field.label}`"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
style="width: 100%"
|
/>
|
<el-date-picker
|
v-else-if="field.type === 'datetimerange'"
|
v-model="formPayload[field.key]"
|
type="datetimerange"
|
range-separator="至"
|
start-placeholder="开始时间"
|
end-placeholder="结束时间"
|
format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
style="width: 100%"
|
/>
|
<el-select
|
v-else-if="field.type === 'select'"
|
v-model="formPayload[field.key]"
|
:placeholder="`请选择${field.label}`"
|
style="width: 100%"
|
clearable
|
filterable
|
>
|
<el-option
|
v-for="o in getOptions(field)"
|
:key="String(o.value)"
|
:label="o.label"
|
:value="o.value"
|
/>
|
</el-select>
|
<span v-else class="field-value">{{ displayValue(field) }}</span>
|
</el-form-item>
|
</div>
|
</template>
|
<el-empty v-else description="暂无填报项" :image-size="48" />
|
</template>
|
|
<script setup>
|
import { onMounted, watch } from "vue";
|
import { useSelectOptionSources } from "../../approve-template/useSelectOptionSources.js";
|
import { formatFieldDisplayValue } from "../approveListConstants.js";
|
|
const props = defineProps({
|
fields: { type: Array, default: () => [] },
|
formPayload: { type: Object, default: () => ({}) },
|
readonly: { type: Boolean, default: false },
|
});
|
|
const { loading: optionSourceLoading, ensureForFields, getOptions, getDisplayLabel } =
|
useSelectOptionSources();
|
|
async function loadOptionCaches() {
|
await ensureForFields(props.fields);
|
}
|
|
onMounted(() => {
|
loadOptionCaches();
|
});
|
|
watch(
|
() => props.fields,
|
() => {
|
loadOptionCaches();
|
},
|
{ deep: true }
|
);
|
|
function displayValue(field) {
|
const val = props.formPayload?.[field.key];
|
if (field.type === "select" && field.optionSource && field.optionSource !== "static") {
|
return getDisplayLabel(field, val);
|
}
|
return formatFieldDisplayValue(field, val);
|
}
|
</script>
|
|
<style scoped>
|
.form-payload-desc {
|
width: 100%;
|
}
|
.form-payload-desc :deep(.el-descriptions__label) {
|
width: 120px;
|
font-weight: 500;
|
}
|
.field-value {
|
color: var(--el-text-color-primary);
|
line-height: 1.6;
|
word-break: break-word;
|
}
|
.form-payload-edit {
|
width: 100%;
|
}
|
</style>
|