<template>
  <view class="dynamic-form">
    <view v-for="(group, gi) in fields" :key="gi" class="form-group">
      <!-- single -->
      <block v-if="group.type === 'single'">
        <view v-if="group.field.type === 'text'" class="form-item">
          <text :class="['form-label', group.field.is_required === true ? 'required' : '']">{{ group.field.label
          }}</text>
          <input type="text" :value="formData[group.field.key]" :placeholder="group.field.placeholder"
            placeholder-class="placeholder" class="form-input" @input="onInput(group.field.key, $event)" />
        </view>
        <view v-else-if="group.field.type === 'number'" class="form-item"
          :style="group.field.tip ? 'flex-wrap: wrap;' : ''">
          <text :class="['form-label', group.field.is_required === true ? 'required' : '']">{{ group.field.label
          }}</text>
          <input type="digit" :value="formData[group.field.key]" :placeholder="group.field.placeholder"
            placeholder-class="placeholder" class="form-input" @input="onInput(group.field.key, $event)" />
          <text v-if="group.field.tips && !group.field.tip" class="form-tips">{{ group.field.tips }}</text>
          <view v-if="group.field.tip" class="price-tip">
            <text class="price-tip-card">{{ group.field.tip }}</text>
          </view>
        </view>
        <view v-else-if="group.field.type === 'image_multi'" class="form-item-up upload-item">
          <view>
            <text :class="['form-label', group.field.is_required === true ? 'required' : '']">{{ group.field.label
            }}</text>
            <text class="upload-tip">(仅可上传{{ group.field.maxCount || 9 }}个图片)</text>
          </view>
          <view class="upload-content">
            <form-item-image :value="formData[group.field.key]" :maxCount="group.field.maxCount || 9"
              @input="onInput(group.field.key, $event)" />
          </view>
        </view>
        <view v-else-if="group.field.type === 'video'" class="form-item-up upload-item">
          <view>
            <text :class="['form-label', group.field.is_required === true ? 'required' : '']">{{ group.field.label
            }}</text>
            <text class="upload-tip">(仅可上传{{ group.field.maxCount || 1 }}个视频)</text>
          </view>
          <view class="upload-content">
            <form-item-video :value="formData[group.field.key]" :maxCount="group.field.maxCount || 1"
              :maxSize="group.field.maxSize || group.field.maxFileSize || 100"
              :userId="uploadUserId"
              @input="onInput(group.field.key, $event)" />
          </view>
        </view>
        <view v-else-if="group.field.type === 'richtext_editor'" class="form-item">
          <text :class="['form-label', group.field.is_required === true ? 'required' : '']">{{ group.field.label
            }}</text>
          <form-item-richtext :value="formData[group.field.key]" @input="onInput(group.field.key, $event)" />
        </view>
        <view v-else-if="group.field.type === 'service_step'" class="form-item-up upload-item">
          <form-item-service-step :value="formData[group.field.key]" :label="group.field.label"
            :required="group.field.is_required === true" @input="onInput(group.field.key, $event)" />
        </view>
      </block>
      <!-- section -->
      <view v-if="group.type === 'section'" class="section-card">
        <view v-if="group.sectionTitle" class="section-title-bar">
          <text class="section-title">{{ group.sectionTitle }}</text>
        </view>
        <view v-for="(field, fi) in group.fields" :key="field.key || fi" class="section-field">
          <view v-if="field.type === 'text'" class="form-item no-bg">
            <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
            <input type="text" :value="formData[field.key]" :placeholder="field.placeholder"
              placeholder-class="placeholder" class="form-input" @input="onInput(field.key, $event)" />
          </view>
          <view v-else-if="field.type === 'textarea'" class="detail-row">
            <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
            <view class="detail-textarea-wrap">
              <textarea class="detail-textarea" :value="formData[field.key]" :placeholder="field.placeholder"
                placeholder-class="placeholder" maxlength="200" @input="onInput(field.key, $event)" />
              <text class="detail-count">{{ (formData[field.key] || "").length }}/200</text>
            </view>
          </view>
          <view v-else-if="field.type === 'number'" class="form-item no-bg"
            :style="field.tip ? 'flex-wrap: wrap;' : ''">
            <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
            <input type="digit" :value="formData[field.key]" :placeholder="field.placeholder"
              placeholder-class="placeholder" class="form-input" @input="onInput(field.key, $event)" />
            <text v-if="field.tips && !field.tip" class="form-tips">{{ field.tips }}</text>
            <view v-if="field.tip" class="price-tip">
              <text class="price-tip-card">{{ field.tip }}</text>
            </view>
          </view>
          <view v-else-if="field.type === 'select'" class="form-item no-bg">
            <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
            <form-item-select :value="formData[field.key]" :options="field.options || []"
              :placeholder="field.placeholder" @input="onInput(field.key, $event)" />
          </view>
          <view v-else-if="field.type === 'single_select'" class="form-item no-bg" style="flex-wrap: wrap;">
            <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
            <view class="select-options">
              <form-item-radio :value="formData[field.key]" :options="field.options || []"
                @input="onInput(field.key, $event)" />
            </view>
          </view>
          <view v-else-if="field.type === 'multi_select'" class="form-item no-bg" style="flex-wrap: wrap;">
            <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
            <view class="select-options">
              <form-item-checkbox :value="formData[field.key]" :options="field.options || []"
                :maxCount="field.maxCount || 0" @input="onInput(field.key, $event)" />
            </view>
          </view>
          <view v-else-if="field.type === 'image_multi'" class="form-item-up upload-item no-bg">
            <view>
              <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
              <text class="upload-tip">(仅可上传{{ field.maxCount || 9 }}个图片)</text>
            </view>
            <view class="upload-content">
              <form-item-image :value="formData[field.key]" :maxCount="field.maxCount || 9"
                @input="onInput(field.key, $event)" />
            </view>
          </view>
          <view v-else-if="field.type === 'video'" class="form-item-up upload-item no-bg">
            <view>
              <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
              <text class="upload-tip">(仅可上传{{ field.maxCount || 1 }}个视频)</text>
            </view>
            <view class="upload-content">
              <form-item-video :value="formData[field.key]" :maxCount="field.maxCount || 1"
                :maxSize="field.maxSize || field.maxFileSize || 100" :userId="uploadUserId"
                @input="onInput(field.key, $event)" />
            </view>
          </view>
          <view v-else-if="field.type === 'richtext_editor'" class="form-item no-bg">
            <text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
            <form-item-richtext :value="formData[field.key]" @input="onInput(field.key, $event)" />
          </view>
          <view v-else-if="field.type === 'service_step'" class="form-item-up upload-item no-bg">
            <form-item-service-step :value="formData[field.key]" :label="field.label"
              :required="field.is_required === true" @input="onInput(field.key, $event)" />
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
import FormItemText from './FormItemText.vue';
import FormItemTextarea from './FormItemTextarea.vue';
import FormItemNumber from './FormItemNumber.vue';
import FormItemImage from './FormItemImage.vue';
import FormItemVideo from './FormItemVideo.vue';
import FormItemSelect from './FormItemSelect.vue';
import FormItemRadio from './FormItemRadio.vue';
import FormItemCheckbox from './FormItemCheckbox.vue';
import FormItemRichtext from './FormItemRichtext.vue';
import FormItemServiceStep from './FormItemServiceStep.vue';

export default {
  name: 'DynamicForm',
  components: {
    'form-item-text': FormItemText,
    'form-item-textarea': FormItemTextarea,
    'form-item-number': FormItemNumber,
    'form-item-image': FormItemImage,
    'form-item-video': FormItemVideo,
    'form-item-select': FormItemSelect,
    'form-item-radio': FormItemRadio,
    'form-item-checkbox': FormItemCheckbox,
    'form-item-richtext': FormItemRichtext,
    'form-item-service-step': FormItemServiceStep
  },
  props: {
    fields: {
      type: Array,
      default: function () { return []; }
    },
    value: {
      type: Object,
      default: function () { return {}; }
    },
    uploadUserId: {
      type: [Number, String],
      default: null
    }
  },
  data: function () {
    return {
      formData: {}
    };
  },
  watch: {
    value: {
      handler: function (val) {
        this.formData = Object.assign({}, val);
      },
      immediate: true
    },
    fields: {
      handler: function () {
        var self = this;
        var data = {};
        this.fields.forEach(function (group) {
          if (group.type === 'single' && group.field) {
            self._initFieldData(data, group.field);
          } else if (group.type === 'section' && group.fields) {
            group.fields.forEach(function (field) {
              self._initFieldData(data, field);
            });
          }
        });
        this.formData = Object.assign({}, this.formData, data);
      },
      immediate: true
    }
  },
  methods: {
    _initFieldData: function (data, field) {
      if (this.formData[field.key] !== undefined) {
        data[field.key] = this.formData[field.key];
      } else if (field.default_value !== undefined) {
        data[field.key] = field.default_value;
      } else if (
        field.type === 'multi_select' ||
        field.type === 'image_multi' ||
        field.type === 'service_step' ||
        (field.type === 'video' && field.maxCount > 1)
      ) {
        data[field.key] = [];
      } else {
        data[field.key] = '';
      }
    },
    onInput: function (key, event) {
      var value = event;
      if (event && event.target && event.target.value !== undefined) {
        value = event.target.value;
      }
      this.$set(this.formData, key, value);
      this.$emit('input', this.formData);
    },
    getData: function () {
      return Object.assign({}, this.formData);
    },
    validate: function () {
      var self = this;
      for (var i = 0; i < this.fields.length; i++) {
        var group = this.fields[i];
        var fieldsToCheck = [];
        if (group.type === 'single' && group.field) {
          fieldsToCheck.push(group.field);
        } else if (group.type === 'section' && group.fields) {
          fieldsToCheck = group.fields;
        }
        for (var j = 0; j < fieldsToCheck.length; j++) {
          var field = fieldsToCheck[j];
          if (field.is_required === true) {
            var value = self.formData[field.key];
            if (!value || (Array.isArray(value) && value.length === 0)) {
              uni.showToast({
                title: field.label + '不能为空',
                icon: 'none'
              });
              return false;
            }
          }
        }
      }
      return true;
    }
  }
};
</script>

<style scoped>
.dynamic-form {
  width: 100%;
}

.form-group {
  width: 100%;
}

.form-item {
  background-color: #fff;
  padding: 24rpx;
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  align-items: center;
  box-sizing: border-box;
  border-radius: 10rpx;
  margin-bottom: 24rpx;
}

.form-label {
  font-size: 28rpx;
  color: #333333;
}

.required::before {
  content: '*';
  color: #ff0000;
  margin-right: 4rpx;
}

.form-tips {
  font-size: 24rpx;
  color: #333333;
  margin-left: 0;
}

.price-tip {
  width: 100%;
  margin-top: 40rpx;
}

.price-tip-card {
  padding: 8rpx 12rpx;
  background: #FDF0F0;
  border-radius: 8rpx;
  font-weight: 400;
  font-size: 24rpx;
  color: #E8101E;
  line-height: 32rpx;
}

.form-item-up {
  background-color: #fff;
  padding: 24rpx;
  display: flex;
  flex-flow: column nowrap;
  justify-content: space-between;
  align-items: flex-start;
  box-sizing: border-box;
  border-radius: 10rpx;
  margin-bottom: 24rpx;
}

.upload-item {
  padding-bottom: 30rpx;
}

.upload-tip {
  font-size: 24rpx;
  color: #999999;
  margin-left: 10rpx;
}

.upload-content {
  margin-top: 20rpx;
  width: 100%;
}

.select-options {
  width: 100%;
  margin-top: 16rpx;
}

.section-card {
  background: #ffffff;
  border-radius: 20rpx;
  padding: 0 24rpx 24rpx;
  margin-bottom: 24rpx;
  box-sizing: border-box;
  overflow: hidden;
}

/* section内字段间距20rpx，通过section-field包装器控制 */
.section-field+.section-field {
  padding-top: 12rpx;
}

/* section内字段去掉独立白色背景和底部间距 */
.section-card .form-item,
.section-card .form-item-up {
  background-color: transparent;
  padding-left: 0;
  padding-right: 0;
  margin-bottom: 0;
  border-radius: 0;
}

.section-card .detail-row {
  padding-top: 0;
  padding-bottom: 0;
}

.section-title-bar {
  padding: 0;
  margin: 0;
}

.section-title {
  padding: 24rpx 0 20rpx;
  font-size: 30rpx;
  font-weight: 500;
  color: #333;
  line-height: 40rpx;
  display: block;
}

.detail-row {
  padding: 20rpx 0 0;
}

.detail-row:first-child {
  padding-top: 0;
}

.detail-row .form-label {
  display: block;
  margin-bottom: 20rpx;
  line-height: 40rpx;
}

.detail-textarea-wrap {
  position: relative;
  background: #f7f7f7;
  border-radius: 16rpx;
  padding: 24rpx 24rpx 52rpx;
  box-sizing: border-box;
}

.detail-textarea {
  width: 100%;
  height: 108rpx;
  min-height: 108rpx;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  font-size: 28rpx;
  line-height: 40rpx;
  color: #333333;
  box-sizing: border-box;
}

.detail-count {
  position: absolute;
  right: 24rpx;
  bottom: 16rpx;
  font-size: 22rpx;
  color: #999999;
  line-height: 32rpx;
}
</style>
