index.vue 4.46 KB
<style>
.eagle-detail {
  padding: 0px;
}
.eagle-detail__group-title {
  font-weight: bold;
  padding: 15px 5px;
  border-bottom: 1px solid #d9d9d9;
  margin-bottom: 30px;
}
.eagle-detail__group-icon {
  padding-right: 10px;
}
.eagle-detail__group-content {
  margin: 15px 0px;
}
</style>

<template>
  <el-form class="eagle-detail" :model="model" v-bind="{ size: 'small', 'label-width': '80px', 'label-position': 'right', ...formProps }">
    <el-row :gutter="15">
      <template v-for="(data, index) in listOption.dataList">
        <template v-if="listOption.isGroup">
          <slot v-if="$scopedSlots[data.key] || $slots[data.key]" :name="data.key" v-bind="data"></slot>
          <el-col v-else class="eagle-detail__group-title" :span="24" :key="data.key">
            <i v-if="data.icon" :class="`el-icon-${data.icon} eagle-detail__group-icon`"></i>
            <span>{{ data.label }}</span>
          </el-col>
        </template>
        <el-row :class="{ 'eagle-detail__group-content': listOption.isGroup }" :key="'group-content-' + index" :gutter="15">
          <template v-for="(item, index) in data.list">
            <el-col :key="index + 'data'" :span="!item.span ? span : item.span">
              <el-form-item :label="item.label" :label-width="item.label ? undefined : item.labelWidth || '0px'" :prop="item.key">
                <slot v-if="$scopedSlots[`item-${item.key}`] || $slots[`item-${item.key}`]" :name="`item-${item.key}`" :model="model" v-bind="item"></slot>
                <label v-else>{{ model[item.key] }}</label>
              </el-form-item>
            </el-col>
          </template>
        </el-row>
      </template>
    </el-row>
  </el-form>
</template>

<script>
export default {
  name: 'Detail',
  props: {
    // 用于实例化本组件绑定v-model的值
    value: {
      type: Object,
      default: () => {
        return {};
      }
    },
    // 配置列表
    list: {
      type: Array,
      required: true
    },
    // 表单参数
    formProps: {
      type: Object,
      default() { return {} }
    },
    // 表单项占位
    span: {
      type: Number,
      default: 8
    }
  },
  data() {
    return {
      // 编辑器表单模型
      model: {}
    };
  },
  created() {
    // 初始化表单模型
    this.initModel(this.list);
  },
  mounted() {
    this.setModelValue(this.value);
  },
  computed: {
    // 配置列表键值对形式
    listKeySet() {
      let result = {};
      this.list.forEach(item => {
        result[item.key] = item;
      });
      return result;
    },
    // 配置列表解析为渲染配置项
    listOption() {
      let groupSet = {};
      this.list.forEach(data => {
        if (data.group) {
          if (typeof data.group === 'object') {
            if (!groupSet[`group-${data.group.key}`]) {
              groupSet[`group-${data.group.key}`] = {
                icon: data.group.icon,
                label: data.group.label,
                list: []
              };
            }
            groupSet[`group-${data.group.key}`].list.push(data);
          } else if (typeof data.group === 'string') {
            if (!groupSet[data.group]) {
              groupSet[data.group] = {
                label: data.group,
                list: []
              };
            }
            groupSet[data.group].list.push(data);
          }
        } else {
          if (!groupSet['group-default']) {
            groupSet['group-default'] = {
              label: '基本信息',
              list: []
            };
          }
          groupSet['group-default'].list.push(data);
        }
      });
      const isGroup = Object.keys(groupSet).length > 1;
      const dataList = Object.keys(groupSet).map(key => {
        return { key, ...groupSet[key] };
      })
      return { isGroup, dataList };
    }
  },
  watch: {
    // 组件外部v-model值更新后同步刷新model
    value(val) {
      this.setModelValue(val);
    },
    // 配置列表有改动时初始化表单模型
    list(value) {
      this.initModel(value);
    },
    model: {
      handler(val) {
        this.$emit("input", val);
        this.$emit("change", val);
      },
      deep: true
    }
  },
  methods: {
    // 设置表单值
    setModelValue(value) {
      Object.keys(this.model).forEach(key => {
        this.model[key] = value ? value[key] : undefined;
      });
    },
    // 初始化表单模型
    initModel(list) {
      list.forEach(item => {
        this.$set(this.model, item.key, item.default || undefined)
      });
    },
  }
};
</script>