ConstructionDailyReportFormSection.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <script setup lang="ts">
  2. import { getStrDictOptions } from '@/utils/dict'
  3. import type {
  4. ConstructionDailyReportField,
  5. ConstructionDailyReportRow,
  6. ConstructionDailyReportSection
  7. } from './report-config'
  8. const props = defineProps<{
  9. model: ConstructionDailyReportRow
  10. section: ConstructionDailyReportSection
  11. disabled: boolean
  12. }>()
  13. const emits = defineEmits<{
  14. (e: 'update:model', value: ConstructionDailyReportRow): void
  15. }>()
  16. function isNumberField(value: unknown) {
  17. return value === null || value === undefined || typeof value === 'number'
  18. }
  19. function updateField(prop: keyof ConstructionDailyReportRow, value: unknown) {
  20. emits('update:model', {
  21. ...props.model,
  22. [prop]: value
  23. })
  24. }
  25. function getNumberValue(prop: keyof ConstructionDailyReportRow) {
  26. const value = props.model[prop]
  27. return typeof value === 'number' ? value : undefined
  28. }
  29. function isFieldDisabled(field: ConstructionDailyReportField) {
  30. return props.disabled || !field.editableInEdit
  31. }
  32. function getDictOptions(field: ConstructionDailyReportField) {
  33. return field.dictType ? getStrDictOptions(field.dictType) : []
  34. }
  35. </script>
  36. <template>
  37. <div class="flex flex-col gap-4">
  38. <div class="flex items-center gap-2">
  39. <div class="h-5 w-1 rounded-full bg-[var(--el-color-primary)]"></div>
  40. <div class="text-lg font-medium text-[var(--el-text-color-primary)]">
  41. {{ props.section.title }}
  42. </div>
  43. </div>
  44. <div class="grid grid-cols-2 gap-4">
  45. <el-form-item
  46. v-for="field in props.section.fields"
  47. :key="`${props.section.title}-${String(field.prop)}-${field.label}`"
  48. :label="field.label"
  49. :prop="field.prop"
  50. :class="{ 'col-span-2': field.span === 2 }"
  51. >
  52. <el-input
  53. v-if="field.type === 'textarea'"
  54. size="default"
  55. :model-value="props.model[field.prop]"
  56. type="textarea"
  57. :autosize="{ minRows: 3 }"
  58. resize="none"
  59. :disabled="isFieldDisabled(field)"
  60. @update:model-value="updateField(field.prop, $event)"
  61. />
  62. <el-select
  63. v-else-if="field.type === 'select'"
  64. size="default"
  65. :model-value="props.model[field.prop]"
  66. :options="getDictOptions(field)"
  67. class="w-full"
  68. clearable
  69. placeholder="请选择"
  70. :disabled="isFieldDisabled(field)"
  71. @update:model-value="updateField(field.prop, $event)"
  72. />
  73. <el-input-number
  74. v-else-if="field.type === 'number' || isNumberField(props.model[field.prop])"
  75. :model-value="getNumberValue(field.prop)"
  76. class="!w-full"
  77. :controls="false"
  78. :min="0"
  79. size="default"
  80. :precision="field.precision"
  81. :disabled="isFieldDisabled(field)"
  82. @update:model-value="updateField(field.prop, $event)"
  83. />
  84. <el-input
  85. v-else
  86. size="default"
  87. :model-value="props.model[field.prop]"
  88. :disabled="isFieldDisabled(field)"
  89. @update:model-value="updateField(field.prop, $event)"
  90. />
  91. </el-form-item>
  92. </div>
  93. </div>
  94. </template>
  95. <style scoped>
  96. :deep(.el-form-item) {
  97. margin-bottom: 0;
  98. }
  99. </style>